简体   繁体   English

引用字符变量时,指针变量的地址存储在哪里?

[英]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? 指针example是否仅具有其自己的地址?

  2. Do the strings I have within the array each have a memory address different to *example 我在数组中拥有的字符串的每个存储地址是否都与*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? 指针example是否只是引用了每个地址,并且还初始化了每个地址(如字符串声明所示)?

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. 我只使用C几个月,所以我只是想抓住事物的本质,而且我听说指针是C的最重要方面。

Does the variable example simply have it's own address? 变量example是否仅具有其自己的地址?

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? 我在数组中拥有的字符串是否每个都有一个与*example不同的内存地址?

Yes, each string has its own address, different from each other's. 是的,每个字符串都有自己的地址,彼此不同。 It's also different from the address of the variable example . 它也与变量example的地址不同。 The expression *example , however, is not the same as the variable example . 但是,表达式*example与变量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. 可变example字符串数组引用在这个意义上的 example而不是它的地址)是数组的地址。

static char* example[] declares example as an array of pointers to char . static char* example[] example声明为指向char的指针的数组。 The array is initialized to three string literals, so example[0] is "doctor" , example[1] is "who" , and example[2] is "hello" . 数组被初始化为三个字符串文字,因此example[0]"doctor"example[1]"who"example[2]"hello"

Since example is an array, the array identifier example is going to evaluate to the address of the array's first element. 由于example是一个数组,因此数组标识符example将求值为数组第一个元素的地址。 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具有array of pointers to char的类型array of pointers to char

&example has the type pointer to array of pointers to char &example具有pointer to array of pointers to char的类型pointer to array of pointers to char

&example[0] has the type pointer to pointer to char . &example[0]的类型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). 第一个将与数组具有相同的地址,但是其他个将通过系统上指针的大小从该地址偏移(对于32位系统,通常为4个字节,对于64位系统,通常为8个字节)。

The char that each pointer in your array example is pointing to is the first char of a string literal. char ,在你的阵列中的每个指针example指向是第一char字符串文字的。 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]是指向char的指针数组中的第一个指针的地址。

example[0] is the first pointer in the array of pointers. example[0]是指针数组中的第一个指针。 Think of an array of int . 想想一个int数组。 Each element of that array would have an address and a value, the latter being an int . 该数组的每个元素都有一个地址和一个值,后者是一个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 . 由于example是一个指针数组,每个元件example都将有一个地址和一个值,后者是一个指针

You can repeat the exercise for &example[1] , etc: 您可以针对&example[1]等重复练习:

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. 指向 char 的指针数组与其第一个元素具有相同的地址。
  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. 这些指针中的每一个都指向一个字符串(字符串的第一个char ),该字符串具有自己的地址。

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. 您将得到一个大小为3的数组,每个数组包含一个char *指针。 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 . 字符串文字"doctor""who""hello"都以在程序的生命周期内分配的方式存储(它们具有静态存储持续时间 ),并且可以以只读方式存储。数据段1

The string literal "doctor" is stored at address 0x00004000 , "who" is stored at address 0x00004007 , and "hello" is stored at address 0x0000400b . 字符串文字"doctor"存储在地址0x00004000"who"存储在地址0x00004007"hello"存储在地址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. 数组example借助static关键字也具有静态存储持续时间,但是实际上,它可能存储在与字符串文字不同的存储区域中。 The array starts at address 0x80001000 , and each element occupies four bytes, so &example[0] == 0x80001000 , &example[1] == 0x80001004 , and &example[2] == 0x80001008 . 数组从地址0x80001000开始,每个元素占用四个字节,因此&example[0] == 0x80001000&example[1] == 0x80001004&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. 请注意,对于名为example的变量,它没有单独的存储位置,该变量指向数组的第一个元素。 In C, the address of the first element is the same as the address of the array itself. 在C语言中,第一个元素的地址与数组本身的地址相同。 This is important , and is one of the most consistently misunderstood aspects of the C language. 这很重要 ,并且是C语言最常被误解的方面之一。 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. 相反,在大多数情况下2 ,数组表达式将被转换(“衰减”)为指针表达式,并且表达式的值将是第一个元素的地址。 If you're really interested, the reasoning for this behavior is outlined in this paper by Dennis Ritchie; 如果您真的很感兴趣,Dennis Ritchie在本文中概述了这种行为的原因。 scroll down to the "Embryonic C" section for the explanation. 向下滚动到“ Embryonic C”部分进行解释。

The value stored in example[0] is the address of the string literal "doctor" . example[0]存储的值是字符串文字"doctor"的地址。 Similarly, example[1] stores the address of the string literal "who" , and example[3] stores the address of the string literal "hello" . 同样, example[1]存储字符串文字"who"的地址, example[3]存储字符串文字"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. 1.因此,尝试修改字符串文字内容的行为未定义 -可能会按预期运行,可能崩溃或无法完全编译。 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. 2.此规则的例外情况是,数组表达式是sizeof的操作数或一元&运算符,或者是用于在声明中初始化另一个数组的字符串文字。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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