简体   繁体   中英

confusion about the way c handles strings

why wouldn't

   char *name = "asd";
   printf("%p\n%p", (void *)&name, (void *)&name[0]);

give the same output as

char name[] = "asd";
printf("%p\n%p", (void *)&name, (void *)&name[0]);

i've read that c takes strings as a pointer to their first char, till it reaches the \\0 but the code above doesn't like it, so it confusing for ac beginner

First, let's give your two variables different names and contents, so we can clearly tell them apart.

char *namep = "asd";
char name[] = "zxc";

These result in data structures which might look like this:

       +-------+
namep: |   *   |
       +---|---+
           |
          /
         |
         V
       +---+---+---+----+
       | a | s | d | \0 |
       +---+---+---+----+

       +---+---+---+----+
namea: | z | x | c | \0 |
       +---+---+---+----+

Now let's look at your two printf calls:

printf("%p\n%p", (void *)&namep, (void *)&namep[0]);

Now, &namep gives you the address of the namep pointer.
But &namep[0] gives you the address of the first character in the pointed-to string ( a ). If you had printed

printf("%p\n", (void *)namep);

you would have seen the same thing.

printf("%p\n%p", (void *)&namea, (void *)&namea[0]);

Here, &namea gives you the address of the array.
And &namea[0] gives you the address of its first character ( z ) — which is the same place. And in fact, due to the special handling (the "decay" of arrays into pointers), if you had said

printf("%p\n", (void *)namea);

you would also have seen the same thing.

You asked:

i've read that c takes strings as a pointer to their first char, till it reaches the \\0

That's correct.

Suppose you wrote the code

char *p;
for(p = namep; *p != '\0'; p++)
    putchar(*p);

This would print your namep string, asd . There's no mystery here. namep was already a pointer, pointing at the first character of the string, so this scrap of code takes its own pointer p , which starts pointing where namep points, and prints the pointed-to characters until it gets to the terminating \\0 .

What's perhaps more surprising is that you can do exactly the same thing with namea :

char *p;
for(p = namea; *p != '\0'; p++)
    putchar(*p);

This works, too, printing zxc , and if you don't believe me, I encourage you to type it into your C compiler and try it.

Now, you may be asking, if p is a pointer and namea is an array, how can the loop initialization p = namea work? And this, again, is due to the "decay" of arrays to pointers. Again, when you try to use namea 's value like this, what you get — the value that gets assigned to p — is automatically a pointer to namea 's first element. And of course that's just what you want. p starts there, and prints characters 'til it finds a \\0 , thus printing zxc .

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