This question already has an answer here:
-
What is the difference between char s[] and char *s?
12 answers
I've read so many threads and questions about it and read so many answers but STILL having difficulties understanding the differences and when you should use what ?
I think you should use char* when you need to store data and you don't know the size of it because it's dynamic.
Also I'm not sure if i'm right but from what I've understand if you declare a char* and assign it a literal text like this :
char *ch = "hi";
it's a constant that you can't change and if you do try to change it you'll just point ch to another allocated memory space holding the new string ?
If write it this way :
char ch = malloc(20);
then you can change the value
and if you do this :
char ch[] = "hi";
char pch = ch;
you can change the values aswell because you point to the array and the arrays points to ch[0] ?
All the is written in bold is my understanding from reading, although I'm probably wrong about most of the stuff I just said and that's why I need a REALLY GOOD and simple explanation so I could once and for all understand the differences and when I should use what.
EDIT :
#include <stdio.h>
main()
{
char ch[] = "Hello";
char *p1 = ch;
char *p2 = p1;
char *p3 = *p1;
printf("ch : %s\n", ch);
printf("p1 address [%d] value is %s\n", p1, *p1);
printf("p2 address [%d] value is %s\n", p2, *p2);
printf("p3 address [%d] value is %s\n", p3, *p3);
return 0;
}
The most straightforward answer is:
The difference here is that
char *s = "Hello world";
will place Hello world in the read-only parts of the memory and making
s a pointer to that, making any writing operation on this memory
illegal. While doing:
char s[] = "Hello world";
puts the literal string in read-only memory and copies the string to
newly allocated memory on the stack. Thus making
s[0] = 'J';
legal.
A more lengthy explanation would include what segments the memory is stored in, and how much memory is allocated:
Example: Allocation Type: Read/Write: Storage Location: Memory Used (Bytes):
===========================================================================================================
const char* str = "Stack"; Static Read-only Code segment 6 (5 chars plus '\0')
char* str = "Stack"; Static Read-only Code segment 6 (5 chars plus '\0')
char* str = malloc(...); Dynamic Read-write Heap Amount passed to malloc
char str[] = "Stack"; Static Read-write Stack 6 (5 chars plus '\0')
char strGlobal[10] = "Global"; Static Read-write Data Segment (R/W) 10
References
- What is the difference between char s[] and char *s in C?, Accessed 2014-09-03,
<https://stackoverflow.com/questions/1704407/what-is-the-difference-between-char-s-and-char-s-in-c>
- Difference between declared string and allocated string, Accessed 2014-09-03,
<https://stackoverflow.com/questions/16021454/difference-between-declared-string-and-allocated-string>
Edit
To address the edit in the question and the comment issued with it, I've added notes to your solution:
#include <stdio.h>
int main() {
char ch[] = "Hello"; /* OK; Creating an array of 6 bytes to store
* 'H', 'e', 'l', 'l', 'o', '\0'
*/
char *p1 = ch; /* OK; Creating a pointer that points to the
* "Hello" string.
*/
char *p2 = p1; /* OK; Creating a second pointer that also
* points to the "Hello" string.
*/
char *p3 = *p1; /* BAD; You are assigning an actual character
* (*p1) to a pointer-to-char variable (p3);
* It might be more intuitive if written in
* 2 lines:
* char* p3;
* p3 = *p1; //BAD
*/
printf("ch : %s\n", ch); /* OK */
printf("p1 address [%d] value is %s\n", p1, *p1); /* Bad format specifiers */
printf("p2 address [%d] value is %s\n", p2, *p2); /* Bad format specifiers */
printf("p3 address [%d] value is %s\n", p3, *p3); /* Bad format specifiers */
return 0;
}
So, three major bugs.
- You are assigning a
char
value to a pointer-to-char
variable. Your compiler should be warning you about this. (char *p3 = *p1
).
- Depending on your compiler, you may have to use the pointer
%p
format specifier to print out an address rather than the %d
(integer) format specifier.
- You are using the string
%s
specifier with a char
data type (ie: printf("%s", 'c')
is wrong). If you are printing a single character, you use the %c
format specifier, and the matching argument should be a character (ie: 'c', char b, etc). If you are printing an entire string, you use the %s
format specifier, and the argument is a pointer-to-char.
Examples
#include <stdio.h>
int main(void) {
char c = 'H'; // A character
char* pC = &c; // A pointer to a single character; IS NOT A STRING
char cArray[] = { 'H', 'e', 'l', 'l', 'o' }; // An array of characters; IS NOT A STRING
char cString[] = { 'H', 'e', 'l', 'l', 'o', '\0' }; // An array of characters with a trailing NULL charcter; THIS IS A C-STYLE STRING
// You could also replace the '\0' with 0 or NULL, ie:
//char cString[] = { 'H', 'e', 'l', 'l', 'o', (char)0 };
//char cString[] = { 'H', 'e', 'l', 'l', 'o', NULL };
const char* myString = "Hello world!"; // A C-style string; the '\0' is added automatically for you
printf("%s\n", myString); // OK; Prints a string stored in a variable
printf("%s\n", "Ducks rock!"); // OK; Prints a string LITERAL; Notice the use of DOUBLE quotes, " "
printf("%s\n", cString); // OK; Prints a string stored in a variable
printf("%c\n", c); // OK; Prints a character
printf("%c\n", *pC); // OK; Prints a character stored in the location that pC points to
printf("%c\n", 'J'); // OK; Prints a character LITERAL; Notice the use of SINGLE quotes, ' '
/* The following are wrong, and your compiler should be spitting out warnings or even not allowing the
* code to compile. They will almost certainly cause a segmentation fault. Uncomment them if you
* want to see for yourself by removing the "#if 0" and "#endif" statements.
*/
#if 0
printf("%s\n", c); // WRONG; Is attempting to print a character as a string, similar
// to what you are doing.
printf("%s\n", *pC); // WRONG; Is attempting to print a character as a string. This is
// EXACTLY what you are doing.
printf("%s\n", cArray); // WRONG; cArray is a character ARRAY, not a C-style string, which is just
// a character array with the '\0' character at the end; printf
// will continue printing whatever follows the end of the string (ie:
// random memory, junk, etc) until it encounters a zero stored in memory.
#endif
return 0;
}
Code Listing - Proposed Solution
#include <stdio.h>
int main() {
char ch[] = "Hello"; /* OK; Creating an array of 6 bytes to store
* 'H', 'e', 'l', 'l', 'o', '\0'
*/
char *p1 = ch; /* OK; Creating a pointer that points to the
* "Hello" string.
*/
char *p2 = p1; /* OK; Creating a second pointer that also
* points to the "Hello" string.
*/
char *p3 = p1; /* OK; Assigning a pointer-to-char to a
* pointer-to-char variables.
*/
printf("ch : %s\n", ch); /* OK */
printf("p1 address [%p] value is %s\n", p1, p1); /* Fixed format specifiers */
printf("p2 address [%p] value is %s\n", p2, p2); /* Fixed format specifiers */
printf("p3 address [%p] value is %s\n", p3, p3); /* Fixed format specifiers */
return 0;
}
Sample Output
ch : Hello
p1 address [0x7fff58e45666] value is Hello
p2 address [0x7fff58e45666] value is Hello
p3 address [0x7fff58e45666] value is Hello