The same notation is used for pointing at a single character or the first character of a null-terminated string:
char c = 'Z';
char a[] = "Hello world";
char *ptr1 = &c;
char *ptr2 = a; // Points to the 'H' of "Hello world"
char *ptr3 = &a[0]; // Also points to the 'H' of "Hello world"
char *ptr4 = &a[6]; // Points to the 'w' of "world"
char *ptr5 = a + 6; // Also points to the 'w' of "world"
The values in ptr2 and ptr3 are the same; so are the values in ptr4 and ptr5. If you're going to treat some data as a string, it is important to make sure it is null terminated, and that you know how much space there is for you to use. Many problems are caused by not understanding what space is available and not knowing whether the string was properly null terminated.
Note that all the pointers above can be dereferenced as if they were an array:
*ptr1 == 'Z'
ptr1[0] == 'Z'
*ptr2 == 'H'
ptr2[0] == 'H'
ptr2[4] == 'o'
*ptr4 == 'w'
ptr4[0] == 'w'
ptr4[4] == 'd'
ptr5[0] == ptr3[6]
*(ptr5+0) == *(ptr3+6)
Late addition to question
What does
char (*ptr)[N];represent?
This is a more complex beastie altogether. It is a pointer to an array of N characters. The type is quite different; the way it is used is quite different; the size of the object pointed to is quite different.
char (*ptr)[12] = &a;
(*ptr)[0] == 'H'
(*ptr)[6] == 'w'
*(*ptr + 6) == 'w'
Note that ptr + 1 points to undefined territory, but points 'one array of 12 bytes' beyond the start of a. Given a slightly different scenario:
char b[3][12] = { "Hello world", "Farewell", "Au revoir" };
char (*pb)[12] = &b[0];
Now:
(*(pb+0))[0] == 'H'
(*(pb+1))[0] == 'F'
(*(pb+2))[5] == 'v'
You probably won't come across pointers to arrays except by accident for quite some time; I've used them a few times in the last 25 years, but so few that I can count the occasions on the fingers of one hand (and several of those have been answering questions on Stack Overflow). Beyond knowing that they exist, that they are the result of taking the address of an array, and that you probably didn't want it, you don't really need to know more about pointers to arrays.
Answer from Jonathan Leffler on Stack Overflowint main() {
char *a = "abcd";
printf("%p %p\n", a, &a);
int b[3] = {1,2,3};
printf("%p %p", b, &b);
}why does the first print statement gives two different pointers but the second one prints the same pointers? Both a and b are pointers, and the pointer to a pointer should be a different address right?
The same notation is used for pointing at a single character or the first character of a null-terminated string:
char c = 'Z';
char a[] = "Hello world";
char *ptr1 = &c;
char *ptr2 = a; // Points to the 'H' of "Hello world"
char *ptr3 = &a[0]; // Also points to the 'H' of "Hello world"
char *ptr4 = &a[6]; // Points to the 'w' of "world"
char *ptr5 = a + 6; // Also points to the 'w' of "world"
The values in ptr2 and ptr3 are the same; so are the values in ptr4 and ptr5. If you're going to treat some data as a string, it is important to make sure it is null terminated, and that you know how much space there is for you to use. Many problems are caused by not understanding what space is available and not knowing whether the string was properly null terminated.
Note that all the pointers above can be dereferenced as if they were an array:
*ptr1 == 'Z'
ptr1[0] == 'Z'
*ptr2 == 'H'
ptr2[0] == 'H'
ptr2[4] == 'o'
*ptr4 == 'w'
ptr4[0] == 'w'
ptr4[4] == 'd'
ptr5[0] == ptr3[6]
*(ptr5+0) == *(ptr3+6)
Late addition to question
What does
char (*ptr)[N];represent?
This is a more complex beastie altogether. It is a pointer to an array of N characters. The type is quite different; the way it is used is quite different; the size of the object pointed to is quite different.
char (*ptr)[12] = &a;
(*ptr)[0] == 'H'
(*ptr)[6] == 'w'
*(*ptr + 6) == 'w'
Note that ptr + 1 points to undefined territory, but points 'one array of 12 bytes' beyond the start of a. Given a slightly different scenario:
char b[3][12] = { "Hello world", "Farewell", "Au revoir" };
char (*pb)[12] = &b[0];
Now:
(*(pb+0))[0] == 'H'
(*(pb+1))[0] == 'F'
(*(pb+2))[5] == 'v'
You probably won't come across pointers to arrays except by accident for quite some time; I've used them a few times in the last 25 years, but so few that I can count the occasions on the fingers of one hand (and several of those have been answering questions on Stack Overflow). Beyond knowing that they exist, that they are the result of taking the address of an array, and that you probably didn't want it, you don't really need to know more about pointers to arrays.
The very same. A C string is nothing but an array of characters, so a pointer to a string is a pointer to an array of characters. And a pointer to an array is the very same as a pointer to its first element.
Videos
Hi, i don't really understand something about strings and pointers So basically a string is an character array ( correct me if im wrong) and we all know that the name of an array is a constant pointer which means we cannot increment or decrement it Although that i found sometimes they do increment the pointer For exemple
Char*S="hello"; While((*S)!='/0') S++ Please someone explain to me the difference between a string and a character array along with pointers!!
I am still learning c, and I am really confused by this. Any help is appreciated.
A short answer won't do your question justice. You're asking about two of the most significant, but often misunderstood, aspects of C.
First of all, in C, by definition, a string is an array of characters, terminated with a nul character, '\0'.
So if you say
char string1[] = "Hello";
it's as if you had said
char string1[] = {'H', 'e', 'l', 'l', 'o', '\0'};
When you use a string constant like "Hello" in your program, the compiler automatically constructs the array for you, as a convenience.
Next we have the character pointer type, char *. You called this a "string to a char array", but it's really a pointer to a single char. People often refer to char * as being C's "string type", and in a way it is, but it can be a misleading thing to say, because not every char * is a string, and more importantly C has very few mechanisms for automatically managing strings for you. (What I mean is that, in C, you can't just sling strings around as if they were a basic data type, like you can in C++ or BASIC. You typically have to worry about where they're stored, how they're allocated.)
But let's go back to the definition of a string. If a string is an array of characters, then why would a pointer to characters be useful for manipulating strings at all? And the answer is, pointers are always useful for manipulating arrays in C; pointers are so good at manipulating arrays that sometimes it seems as if they are arrays. (But don't worry, they're not.)
I can't delve into a full treatise on the relationship between arrays and pointers in C here, but a couple of points must be made:
If you say something like
char *string2 = "world";
what actually happens (what the compiler does for you automatically) is as if you had written
static char __temporaryarray[] = "world";
char *string2 = __temporaryarray;
And, actually, since string2 is a pointer to a character (that is, what it points at is characters, not whole arrays of characters), it's really:
char *string2 = &__temporaryarray[0];
(That is, the pointer actually points to the array's first element.)
So since a string is always an array, when you mentioned the string "world" in a context where you weren't using it to initialize an array, C went ahead and created the array for you, and then made the pointer point to it. C does this whenever you have a string constant lying around in your program. So you can later say
string2 = "sailor";
and you can also say things like
if(strcmp(string1, "Goodbye") == 0) { ... }
Just don't do
char *string3;
strcpy(string3, "Rutabaga"); /* WRONG!! *//
That's very wrong, and won't work reliably at all, because nobody allocates any memory for string3 to point to, for strcpy to copy the string into.
So to answer your question, you will sometimes see strings created or manipulated as if they are arrays, because that's what they actually are. But you will often see them manipulated using pointers (char *), because this can be extremely convenient, as long as you know what you are doing.
Why do I see some books using the pointers method while others use the normal definitions ?
Neither of those is more "normal" than the other. A string in C is purely a contiguous (uninterrupted) series of char terminated with a 0 char. You can refer to that with a char[], or you can refer to it with a char *, or a const char *, etc. They're all just ways of referring to the block of memory with the series of chars in it. Each is appropriate in different contexts, depending on how the code in question receives the string and what it's doing with it.
A pointer contains the address of an object (or is a null pointer that doesn't point to any object). A pointer has a specific type that indicates the type of object it can point to.
An array is a contiguous ordered sequence of elements; each element is an object, and all the elements of an array are of the same type.
A string is defined as "a contiguous sequence of characters terminated by and including the first null character". C has no string type. A string is a data layout, not a data type.
The relationship between arrays and pointers can be confusing. The best explanation I know of is given by section 6 of the comp.lang.c FAQ. The most important thing to remember is that arrays are not pointers.
Arrays are in a sense "second-class citizens" in C and C++. They cannot be assigned, passed as function arguments, or compared for equality. Code that manipulates arrays usually does so using pointers to the individual elements of the arrays, with some explicit mechanism to specify how long the array is.
A major source of confusion is the fact that an expression of array type (such as the name of an array object) is implicitly converted to a pointer value in most contexts. The converted pointer points to the initial (zeroth) element of the array. This conversion does not happen if the array is either:
The operand of
sizeof(sizeof array_objectyields the size of the array, not the size of a pointer);The operand of unary
&(&array_objectyields the address of the array object as a whole); orA string literal in an initializer used to initialize an array object.
char *string = "String";
To avoid confusion, I'm going to make a few changes in your example:
const char *ptr = "hello";
The string literal "hello" creates an anonymous object of type char[6] (in C) or const char[6] (in C++), containing the characters { 'h', 'e', 'l', 'l', 'o', '\0' }.
Evaluation of that expression, in this context, yields a pointer to the initial character of that array. This is a pointer value; there is no implicitly created pointer object. That pointer value is used to initialize the pointer object ptr.
At no time is an array "treated as" a pointer. An array expression is converted to a pointer type.
Another source of confusion is that function parameters that appear to be of array type are actually of pointer type; the type is adjusted at compile time. For example, this:
void func(char param[10]);
really means:
void func(char *param);
The 10 is silently ignored. So you can write something like this:
void print_string(char s[]) {
printf("The string is \"%s\"\n", s);
}
// ...
print_string("hello");
This looks like just manipulating arrays, but in fact the array "hello" is converted to a pointer, and that pointer is what's passed to the print_string function.
So, is this conclusion true or false and why ?
Your conclusion is false.
Arrays and pointers are different. comp.lang.c FAQ list · Question 6.8 explains the difference between arrays and pointers:
An array is a single, preallocated chunk of contiguous elements (all of the same type), fixed in size and location. A pointer is a reference to any data element (of a particular type) anywhere. A pointer must be assigned to point to space allocated elsewhere, but it can be reassigned (and the space, if derived from malloc, can be resized) at any time. A pointer can point to an array, and can simulate (along with malloc) a dynamically allocated array, but a pointer is a much more general data structure.
When you do
char *string = "String";
and when a C compiler encounters this, it sets aside 7 bytes of memory for the string literal String. Then set the pointer string to point to the starting location of the allocated memory.
When you declare
char string[] = "String";
and when a C compiler encounters this, it sets aside 7 bytes of memory for the string literal String. Then gives the name of that memory location, i.e. the first byte, string.
So,
- In first case
stringis a pointer variable and in second case it is an array name. - The characters stored in first case can't be modified while in array version it can be modified.
This means arrays is not considered as pointers in C but they are closely related in the sense that pointer arithmetic and array indexing are equivalent in C, pointers and arrays are different.
There is no difference. The second option is commonly preferred because it makes it easier to avoid this pitfall:
char* str1, str2;
Here, str1 is a char* but str2 is a plain char. The other way of writing the declaration makes it easier to see that you have to put an extra asterisk in there:
char *str1, *str2;
Now both variables are of type char*.
No difference here. But those two below are different:
char *p1, *p2;
and
char* p1, p2;
I dont understand why cwe cant modify the string content !
Because the C standard says so: “If the program attempts to modify such an array [the array defined by a string literal], the behavior is undefined” (C 2018 6.4.5 7). A string literal is a sequence of characters in quotes in source code, such as "Hello, world.\n". (String literals may also be preceded by an encoding prefix u8, u, U, or L, as in L"abc".) A string literal defines an array containing the characters of the string plus a terminating null character.
A reason that attempting to modify the string literal’s array is that string literals were, and are, widely used for strings that are constant—error messages to be printed at times, format strings for printf operations, hard-coded names of things, and so on. As C developed, and the standard was written, it made sense for string literals to be treated as read-only and to allow a compiler to put them in read-only storage. Additionally, some compilers would use the same storage for identical string literals that appeared in different places, and some would use the same storage for a string literal that was a trailing substring of another string literal. Because of this shared storage, modifying one string would also modify the other. So allowing programs to modify string literals could cause some problems.
So, if you merely point to a string literal, you are pointing to something that should not be modified. If you want your own copy that can be modified, simply define it with an array as you show with char amessage[] = "now is the time";. Such a definition defines an array, amessage that has its own storage. That array is initialized with the contents of the string literal but is separate from it.
char amessage[] = "now is the time"; /* an array */
amessage is a modifiable array of chars.
char *pmessage = "now is the time"; /* a pointer */
pmessage is a pointer to the string literal. Attempt to modify the string literal is an Undefined Behaviour.
Replace
char *ch = "girl"
with
char ch[] = "girl"
Where the former creates a pointer to immutable memory, the latter creates a char[] array of the right size and initialises it with the letters of "girl" (including the terminating zero-byte).
UPDATE: thanks to @dreamlax
"girl" is implicitly declared as a char *. But most likely your compiler is putting the string-literals into a section (rostrings) which will later be placed in a protected memory-area. When you try to assign something to *ch it will access this protected (or not depending on your platform) memory.
The compiler should warn you about the char *ch = "girl";.