简体   繁体   中英

Something I don't get about C strings

A few questions regarding C strings:

  1. both char* and char[] are pointers?
  2. I've learned about pointers and I can tell that char* is a pointer, but why is it automatically a string and not just a char pointer that points to 1 char; why can it hold strings?
  3. Why, unlike other pointers, when you assign a new value to the char* pointer you are actually allocating new space in memory to store the new value and, unlike other pointers, you just replace the value stored in the memory address the pointer is pointing at?

A pointer is not a string.
A string is a constant object having type array of char and, also, it has the property that the last element of the array is the null character '\\0' which, in turn, is an int value (converted to char type) having the integer value 0 .

  1. char* is a pointer, but char[] is not. The type char[] is not a "real" type, but an incomplete type . The C language is specified in such a way that, in the moment that you define a concrete variable (object) having array of char type, the size of the array is well determined in some way or another. Thus, none variable has type char[] because this is not a type (for a given object).

    However, automatically every object having type array of N objects of type char is promoted to char * , that is, a pointer to char pointing to the initial object of the array.

    On the other hand, this promotion is not always performed. For example, the operator sizeof() will give different results for char* than for an array of N chars . In the former case, the size of a pointer to char is given (which is in general the same amount for every pointer...), and in the last case gives you the value N , that is, the size of the array.

    The behaviour is differente when you declare function arguments as char* and char[] . Since the function cannot know the size of the array, you can think of both declarations as equivalent.

  2. Actually, you are right here: char * is a pointer to just 1 character object. However, it can be used to access strings, as I will explain you now: In the paragraph 1. I showed you that the strings are considered objects in memory having type array of N chars for some N . This value N is big enough to allow an ending null character (as all "string" is supposed to be in C ).

    So, what's the deal here?

    The key point to understand this issues is the concept of object (in memory) .
    When you have a string or, more generally, an array of char , this means that you have figured out some manner to hold an array object in memory.
    This object determines a portion of RAM memory that you can access safely, because C has assigned enough memory for it.
    Thus, when you point to the first byte of this object with a char* variable, actually you have guaranteed access to all the adjacent elements to the "right" of that memory place, because those places are well defined by C as having the bytes of the array above.

    Briefly: the adjacent (to the right) bytes of the byte pointed by a char* variable can be accessed, they are valid places to access, so the pointer can be "iterated" to walk through these bytes, up to the end of the string, without "risks", since all the bytes in an array are contiguous well defined positions in memory.

  3. This is a complicated question, but it reveals that you are not understanding the relationship between pointers, arrays, and string literals in C .

    • A pointer is just a variable pointing to a position in memory.
    • A pòinter to char points to just 1 object having type char.
    • If the adjacent bytes of the pointed position correspond to an array of chars, they will be accessible by the pointer, so the pointer can "walk on" the memory bytes occupied by the array object.
    • A string literal is considered as an array of char object, which implictely add an ending byte with value 0 (the null character).

    In any case, an array of T object has a well defined "size".
    A string literal has an additional property: it's a constant object.
    Try to fit and gather these concepts in your mind to figure out what's going on.

    And ask me for clarification.

ADDITIONAL REMARKS:

Consider the following piece of code:

#include <stdio.h>
int main(void)
{
   char *s1  = "not modifiable";
   char s2[] = "modifiable";
   printf("%s ---- %s\n\n", s1, s2);
   printf("Size of array s2: %d\n\n", (int)sizeof(s2));

   s2[1] = '0', s2[3] = s2[5] = '1', s2[4] = '7',
   s2[6] = '4', s2[7] = '8', s2[9] = '3';
   printf("New value of s2: %s\n\n",s2);
   //s1[0] = 'X';   // Attempting to modify s1
}

In the definition and initialization of s1 we have the string literal "not modifiable" , which has constant content and constant address. Its address is assigned to the pointer s1 as initialization.
Any attempt to modify the bytes of the string will give some kind of error, because the array content is read-only.

In the definition and initialization of s2 , we have the string literal "modifiable" , which has, again, constant content and constant address. However, what happens now is that, as part of the initialization, the content of the string is copied to the array of char s2 . The size of the array s2 is not specified (the declaration char s2[] gives an incomplete type), but after initialization the size of the array is well determined and defined as the exact size of the copied string (plus 1 character used to hold the null character, or end-of-string mark).

So, the string literal "modifiable" is used to initialize the bytes of the array s2 , which is modifiable.
The right manner to do that is by changing a character at the time.
For more handy ways of modifying and assigning strings, it has to be used the standard header <string.h> .

  1. char *s is a pointer, char s[] is an array of characters. Ex.

     char *s = "hello"; char c[] = "world"; s = c; //Legal c = address of some other string //Illegal 
  2. char *s is not a string; it points to an address. Ex

     char c[] = "hello"; char *s = &c[3]; 
  3. Assigning a pointer is not creating memory; you are pointing to memory. Ex.

     char *s = "hello"; 

    In this example when you type "hello" you are creating special memory to hold the string "hello" but that has nothing to do with the pointer, the pointer simply points to that spot.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM