C语言 为什么数组的地址等于它在 C 中的值?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2528318/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How come an array's address is equal to its value in C?
提问by Alexandre
In the following bit of code, pointer values and pointer addresses differ as expected.
在以下代码中,指针值和指针地址与预期不同。
But array values and addresses don't!
但是数组值和地址没有!
How can this be?
怎么会这样?
Output
输出
my_array = 0022FF00
&my_array = 0022FF00
pointer_to_array = 0022FF00
&pointer_to_array = 0022FEFC
#include <stdio.h>
int main()
{
char my_array[100] = "some cool string";
printf("my_array = %p\n", my_array);
printf("&my_array = %p\n", &my_array);
char *pointer_to_array = my_array;
printf("pointer_to_array = %p\n", pointer_to_array);
printf("&pointer_to_array = %p\n", &pointer_to_array);
printf("Press ENTER to continue...\n");
getchar();
return 0;
}
回答by Jerry Coffin
The name of an array usually evaluates to the address of the first element of the array, so arrayand &arrayhave the same value (but different types, so array+1and &array+1will notbe equal if the array is more than 1 element long).
数组的名称通常计算为数组第一个元素的地址,因此array和&array具有相同的值(但类型不同,因此如果数组长度超过 1 个元素,则array+1和&array+1将不相等)。
There are two exceptions to this: when the array name is an operand of sizeofor unary &(address-of), the name refers to the array object itself. Thus sizeof arraygives you the size in bytes of the entire array, not the size of a pointer.
对此有两个例外:当数组名称是sizeof或一元&(地址)的操作数时,名称指的是数组对象本身。因此sizeof array为您提供整个数组的字节大小,而不是指针的大小。
For an array defined as T array[size], it will have type T *. When/if you increment it, you get to the next element in the array.
对于定义为 的数组T array[size],它将具有类型T *。当/如果你增加它,你会得到数组中的下一个元素。
&arrayevaluates to the same address, but given the same definition, it creates a pointer of the type T(*)[size]-- i.e., it's a pointer to an array, not to a single element. If you increment this pointer, it'll add the size of the entire array, not the size of a single element. For example, with code like this:
&array计算到相同的地址,但给定相同的定义,它创建一个类型的指针T(*)[size]——即,它是一个指向数组的指针,而不是指向单个元素。如果你增加这个指针,它会增加整个数组的大小,而不是单个元素的大小。例如,使用这样的代码:
char array[16];
printf("%p\t%p", (void*)&array, (void*)(&array+1));
We can expect the second pointer to be 16 greater than the first (because it's an array of 16 char's). Since %p typically converts pointers in hexadecimal, it might look something like:
我们可以期望第二个指针比第一个大 16 个(因为它是一个 16 个字符的数组)。由于 %p 通常以十六进制转换指针,因此它可能类似于:
0x12341000 0x12341010
回答by Eli Bendersky
That's because the array name(my_array) is different from a pointer to array. It is an alias to the address of an array, and its address is defined as the address of the array itself.
这是因为数组名称( my_array) 不同于指向数组的指针。它是数组地址的别名,它的地址定义为数组本身的地址。
The pointer is a normal C variable on the stack, however. Thus, you can take its address and get a different value from the address it holds inside.
然而,指针是堆栈上的一个普通 C 变量。因此,您可以获取其地址并获得与其内部保存的地址不同的值。
I wrote about this topic here- please take a look.
我在这里写过这个话题- 请看一看。
回答by CB Bailey
In C, when you use the name of an array in an expression (including passing it to a function), unless it is the operand of the address-of (&) operator or the sizeofoperator, it decaysto a pointer to its first element.
在 C 中,当您在表达式中使用数组的名称时(包括将其传递给函数),除非它是 address-of ( &) 运算符或sizeof运算符的操作数,否则它会衰减为指向其第一个元素的指针。
That is, in most contexts arrayis equivalent to &array[0]in both type and value.
也就是说,在大多数情况下array,&array[0]在类型和值中都等价。
In your example, my_arrayhas type char[100]which decays to a char*when you pass it to printf.
在您的示例中,当您将其传递给 printf 时,my_array类型char[100]会衰减为 a char*。
&my_arrayhas type char (*)[100](pointer to array of 100 char). As it is the operand to &, this is one of the cases that my_arraydoesn't immediately decay to a pointer to its first element.
&my_array具有类型char (*)[100](指向 100 数组的指针char)。由于它是 的操作数&,因此这是my_array不会立即衰减到指向其第一个元素的指针的情况之一。
The pointer to the array has the same address value as a pointer to the first element of the array as an array object is just a contiguous sequence of its elements, but a pointer to an array has a different type to a pointer to an element of that array. This is important when you do pointer arithmetic on the two types of pointer.
指向数组的指针与指向数组第一个元素的指针具有相同的地址值,因为数组对象只是其元素的连续序列,但指向数组的指针与指向数组元素的指针具有不同的类型那个数组。当您对两种类型的指针进行指针运算时,这一点很重要。
pointer_to_arrayhas type char *- initialized to point at the first element of the array as that is what my_arraydecays to in the initializer expression - and &pointer_to_arrayhas type char **(pointer to a pointer to a char).
pointer_to_array具有类型char *- 初始化为指向数组的第一个元素,因为它my_array在初始化表达式中衰减到 - 并且&pointer_to_array具有类型char **(指向 a 的指针的指针char)。
Of these: my_array(after decay to char*), &my_arrayand pointer_to_arrayall point directly at either the array or the first element of the array and so have the same address value.
其中:(my_array衰减到 后char*),&my_array并且pointer_to_array都直接指向数组或数组的第一个元素,因此具有相同的地址值。
回答by R Sahu
The reason why my_arrayand &my_arrayresult in the same address can be easily understood when you look at the memory layout of an array.
当您查看数组的内存布局时,很容易理解为什么my_array和&my_array结果在相同的地址。
Let's say you have an array of 10 characters (instead the 100 in your code).
假设您有一个包含 10 个字符的数组(而不是代码中的 100 个)。
char my_array[10];
Memory for my_arraylooks something like:
内存my_array看起来像:
+---+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+
^
|
Address of my_array.
In C/C++, an array decays to the pointer to the first element in an expression such as
在 C/C++ 中,数组衰减到指向表达式中第一个元素的指针,例如
printf("my_array = %p\n", my_array);
If you examine where the first element of the array lies you will see that its address is the same as the address of the array:
如果您检查数组的第一个元素所在的位置,您将看到它的地址与数组的地址相同:
my_array[0]
|
v
+---+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+
^
|
Address of my_array[0].
回答by supercat
In the B programming language, which was the immediate predecessor to C, pointers and integers were freely interchangeable. The system would behave as though all of memory was a giant array. Each variable name had either a global or stack-relative address associated with it, for each variable name the only things the compiler had to keep track of was whether it was a global or local variable, and its address relative to the first global or local variable.
在 B 编程语言中,它是 C 的直接前身,指针和整数可以自由互换。系统会表现得好像所有内存都是一个巨大的数组。每个变量名都有一个与之关联的全局或堆栈相关地址,对于每个变量名,编译器唯一需要跟踪的是它是全局变量还是局部变量,以及它相对于第一个全局或局部变量的地址多变的。
Given a global declaration like i;[there was no need to specify a type, since everything was an integer/pointer] would be processed by the
compiler as: address_of_i = next_global++; memory[address_of_i] = 0;and a statement like i++would be processed as: memory[address_of_i] = memory[address_of_i]+1;.
给定一个像i;[不需要指定类型,因为一切都是整数/指针]的全局声明将被编译器处理为:address_of_i = next_global++; memory[address_of_i] = 0;并且像i++这样的语句将被处理为: memory[address_of_i] = memory[address_of_i]+1;。
A declaration like arr[10];would be processed as address_of_arr = next_global; memory[next_global] = next_global; next_global += 10;. Note that as soon as that declaration was processed, the compiler could immediately forget about arrbeing an array. A statement like arr[i]=6;would be processed as memory[memory[address_of_a] + memory[address_of_i]] = 6;. The compiler wouldn't care whether arrrepresented an array and ian integer, or vice versa. Indeed, it wouldn't care if they were both arrays or both integers; it would perfectly happily generate the code as described, without regard for whether the resulting behavior would likely be useful.
类似的声明arr[10];将被处理为address_of_arr = next_global; memory[next_global] = next_global; next_global += 10;. 请注意,一旦处理了arr该声明,编译器就会立即忘记它是一个数组。像arr[i]=6;这样的语句将被处理为memory[memory[address_of_a] + memory[address_of_i]] = 6;。编译器不会关心是否arr表示数组和i整数,反之亦然。事实上,它不会在乎它们是数组还是整数;它会很高兴地生成所描述的代码,而不考虑由此产生的行为是否可能有用。
One of the goals of the C programming language was to be largely compatible with B. In B, the name of an array [called a "vector" in the terminology of B] identified a variable holding a pointer which was initially assigned to point to to the first element of an allocation of the given size, so if that name appeared in the argument list for a function, the function would receive a pointer to the vector. Even though C added "real" array types, whose name was rigidly associated with the address of the allocation rather than a pointer variable that would initially point to the allocation, having arrays decompose to pointers made code which declared a C-type array behave identically to B code which declared a vector and then never modified the variable holding its address.
C 编程语言的目标之一是在很大程度上与 B 兼容。在 B 中,数组的名称 [在 B 的术语中称为“向量”] 标识了一个变量,该变量包含一个指针,该指针最初被分配为指向到给定大小的分配的第一个元素,因此如果该名称出现在函数的参数列表中,则该函数将收到一个指向该向量的指针。尽管 C 添加了“真正的”数组类型,其名称与分配的地址严格相关,而不是最初指向分配的指针变量,但将数组分解为指针使得声明 C 类型数组的代码行为相同到 B 代码,它声明了一个向量,然后从不修改保存其地址的变量。
回答by Ravi Bisla
Actually &myarrayand myarrayboth are the base address.
实际上&myarray和myarray两者都是基地址。
If you want to see the difference instead of using
如果您想查看差异而不是使用
printf("my_array = %p\n", my_array);
printf("my_array = %p\n", &my_array);
use
用
printf("my_array = %s\n", my_array);
printf("my_array = %p\n", my_array);

