简体   繁体   中英

Where is a pointer variable's address stored when referencing a character variable?

Let's say we have a character pointer like this:

static char *example[]={"doctor","who","hello"};

I'm slightly confused at what is happening in this instance.

  1. Does the pointer example simply have its own address?

  2. Do the strings I have within the array each have a memory address different to *example
    and each other?

  3. Does the pointer example just simply reference each address and also initialize what's in each address as shown by the declaration of the strings?

I'm only being using C for a few months, so I'm just trying to grasp the nuts and bolts of things, and I hear pointers are single-handedly the most important aspect of C.

Does the variable example simply have it's own address?

Yes, the variable has its own address.

Do the strings I have within the array each have a memory address different to *example and each other?

Yes, each string has its own address, different from each other's. It's also different from the address of the variable example . The expression *example , however, is not the same as the variable example . See the next.

Does the pointer example just simply reference each address and also initialize what's in each address as shown by the declaration of the strings?

The variable example references the array of strings in the sense that the value of example ( not its address) is the address of the array.

static char* example[] declares example as an array of pointers to char . The array is initialized to three string literals, so example[0] is "doctor" , example[1] is "who" , and example[2] is "hello" .

Since example is an array, the array identifier example is going to evaluate to the address of the array's first element. If you try something like this:

printf ("%p %p %p\n", example, &example, &example[0]);

you'll see that they all have the same value. All these, however, are semantically different types .

example has the type array of pointers to char

&example has the type pointer to array of pointers to char

&example[0] has the type pointer to pointer to char .

Each element of the array has its own address. Try this:

printf ("%p %p %p\n", &example[0], &example[1], &example[2]);

The first will be the same address as the array, but the others will be offset from that address by the size of a pointer on your system (typically four bytes for a 32-bit system, 8 bytes for a 64-bit system).

The char that each pointer in your array example is pointing to is the first char of a string literal. Each string literal has its own address, probably in a read-only memory segment. You can try this too:

printf ("%p %p\n", &example[0], example[0]); 

&example[0] is the address of the first pointer in the array of pointers to char .

example[0] is the first pointer in the array of pointers. Think of an array of int . Each element of that array would have an address and a value, the latter being an int . Since example is an array of pointers, each element of example is going to have an address and a value, the latter being a pointer .

You can repeat the exercise for &example[1] , etc:

printf ("%p %p\n", &example[1], example[1]);
printf ("%p %p\n", &example[2], example[2]);

To sum up:

  1. The array of pointers to char has the same address as its first element.
  2. Each subsequent element, ie, each subsequent pointer in the array, has its own address.
  3. Each of those pointers points to (the first char of) a string, which has its own address.

Hope that's clear.

If you declare

char *example[] = {"doctor","who","hello"};

You get an array, of size 3, each of which holds one char* pointer. It is the same as

char *example[3] = {"doctor","who","hello"};

But, we really need to see how example is declared in your code to answer.

A picture might help. The following is not meant to represent any particular architecture - all address values are pulled out of thin air.


Item          Address            0x00  0x01  0x02  0x03
----          -------            ----  ----  ----  ----
              0x00004000          'd'   'o'   'c'   't'
              0x00004004          'o'   'r'  0x00   'w'
              0x00004008          'h'   'o'  0x00   'h'
              0x0000400c          'e'   'l'   'l'   'o'
              0x00004010         0x00    ??    ??    ??
...           ...                ...
example:      0x80001000         0x00  0x00  0x40  0x00
              0x80001004         0x00  0x00  0x40  0x07
              0x80001008         0x00  0x00  0x40  0x0b

The string literals "doctor" , "who" , and "hello" are all stored in such a way that they are allocated over the lifetime of the program (they have static storage duration ), and they may be stored in a read-only data segment 1 .

The string literal "doctor" is stored at address 0x00004000 , "who" is stored at address 0x00004007 , and "hello" is stored at address 0x0000400b .

The array example also has static storage duration by virtue of the static keyword, but in practice will probably be stored in a different memory area than the string literals. The array starts at address 0x80001000 , and each element occupies four bytes, so &example[0] == 0x80001000 , &example[1] == 0x80001004 , and &example[2] == 0x80001008 .

Note that there's no separate storage location for a variable named example that points to the first element of the array. In C, the address of the first element is the same as the address of the array itself. This is important , and is one of the most consistently misunderstood aspects of the C language. Arrays are not pointers ; rather, an array expression will be converted ("decay") to a pointer expression in most circumstances 2 , and the value of the expression will be the address of the first element. If you're really interested, the reasoning for this behavior is outlined in this paper by Dennis Ritchie; scroll down to the "Embryonic C" section for the explanation.

The value stored in example[0] is the address of the string literal "doctor" . Similarly, example[1] stores the address of the string literal "who" , and example[3] stores the address of the string literal "hello" .


1. Because of this, the behavior on trying to modify the contents of a string literal is undefined - it may work as expected, it may crash, or it may fail to compile altogether. The compiler is not required to handle the situation in any particular way, so the behavior will vary between different compilers. You should never attempt to modify the contents of a string literal.

2. The exceptions to this rule are when the array expression is an operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration.

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