为什么会出现数组';s地址等于它在C中的值?
在下面的代码位中,指针值和指针地址与预期不同 但是数组值和地址不能 这怎么可能 输出为什么会出现数组';s地址等于它在C中的值?,c,pointers,arrays,C,Pointers,Arrays,在下面的代码位中,指针值和指针地址与预期不同 但是数组值和地址不能 这怎么可能 输出 my_array = 0022FF00 &my_array = 0022FF00 pointer_to_array = 0022FF00 &pointer_to_array = 0022FEFC #包括 int main() { char my_数组[100]=“some cool string”; printf(“我的\u数组=%p\n”,我的\u数组); printf(&my\u数组=%p
my_array = 0022FF00
&my_array = 0022FF00
pointer_to_array = 0022FF00
&pointer_to_array = 0022FEFC
#包括
int main()
{
char my_数组[100]=“some cool string”;
printf(“我的\u数组=%p\n”,我的\u数组);
printf(&my\u数组=%p\n“,&my\u数组);
char*指向数组的指针=我的数组;
printf(“指向数组的指针=%p\n”,指向数组的指针);
printf(“&pointer\u-to\u-array=%p\n”、&pointer\u-to\u-array”);
printf(“按ENTER键继续…\n”);
getchar();
返回0;
}
这是因为数组名(my_array
)与指向数组的指针不同。它是数组地址的别名,其地址定义为数组本身的地址
但是,指针是堆栈上的普通C变量。因此,您可以获取其地址,并从其内部保存的地址中获取不同的值
我写过关于这个主题的文章-请看。数组的名称通常计算为数组第一个元素的地址,因此
数组
和数组
具有相同的值(但类型不同,因此如果数组长度超过1个元素,数组+1
和&array+1
将不相等)
有两种例外情况:当数组名是sizeof
或一元&
(的地址)的操作数时,该名称指数组对象本身。因此,sizeof array
提供整个数组的字节大小,而不是指针的大小
对于定义为T数组[size]
的数组,其类型将为T*
。当/如果增加它,则进入数组中的下一个元素
&array
的计算结果是相同的地址,但给定相同的定义,它会创建一个类型为T(*)[size]
的指针——即,它是指向数组的指针,而不是指向单个元素的指针。如果增加这个指针,它将增加整个数组的大小,而不是单个元素的大小。例如,使用如下代码:
char array[16];
printf("%p\t%p", (void*)&array, (void*)(&array+1));
我们可以预期第二个指针比第一个指针大16个(因为它是一个由16个字符组成的数组)。由于%p通常以十六进制格式转换指针,因此它可能类似于:
0x12341000 0x12341010
+---+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+
^
|
Address of my_array.
在C语言中,当您在表达式中使用数组的名称(包括将其传递给函数)时,除非它是(
&
)运算符地址的操作数或sizeof
运算符的操作数,否则它将衰减为指向其第一个元素的指针
也就是说,在大多数上下文中,array
在类型和值上都等同于&array[0]
在您的示例中,my_array
具有类型char[100]
,当您将其传递给printf时,该类型会衰减为char*
&my_数组
的类型为char(*)[100]
(指向100的数组的指针char
)。由于它是&
的操作数,这是my_array
不会立即衰减为指向其第一个元素的指针的情况之一
指向数组的指针与指向数组第一个元素的指针具有相同的地址值,因为数组对象只是其元素的连续序列,但指向数组的指针与指向该数组元素的指针具有不同的类型。在对这两种类型的指针执行指针算术时,这一点很重要
指向数组的指针
的类型为char*
-初始化为指向数组的第一个元素,因为这是我的数组
在初始化表达式中衰减为的内容-而指向数组的指针
的类型为char**
(指向char
的指针)
其中:
myu数组
(衰减为char*
)、myu数组
和指向数组的指针
都直接指向数组或数组的第一个元素,因此具有相同的地址值。实际上&myarray
和myarray
都是基地址
如果您想看到差异,而不是使用
printf("my_array = %p\n", my_array);
printf("my_array = %p\n", &my_array);
使用
查看阵列的内存布局时,可以很容易地理解
my_array
和my_array
导致相同地址的原因
假设您有一个10个字符的数组(而不是代码中的100个字符)
my_数组的内存类似于:
0x12341000 0x12341010
+---+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+
^
|
Address of my_array.
在C/C++中,数组衰减到表达式中第一个元素的指针,如
printf("my_array = %p\n", my_array);
如果检查数组的第一个元素所在的位置,您将看到其地址与数组的地址相同:
my_array[0]
|
v
+---+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+
^
|
Address of my_array[0].
在B编程语言中,它是C的直接前身,
指针和整数可以自由互换。该系统将表现为
虽然所有的记忆都是一个巨大的阵列。每个变量名都有一个全局变量
或堆栈相对地址
与之相关联的是,对于每个变量名,编译器只需跟踪它是全局变量还是局部变量,以及它相对于第一个全局变量或局部变量的地址
给定一个全局声明,如i代码>[无需指定类型,因为所有内容都是整数/指针]将由
编译器为:address\u of\u i=next\u global++;内存[地址\的\ i]=0
和类似i++
的语句将被处理为:memory[address\u of_i]=memory[address\u of_i]+1代码>
类似于arr[10]的声明代码>将被处理为address\u of\u arr=next\u global;内存[下一个全局]=下一个全局;下一个_global+=10代码>。请注意,一旦处理了该声明,编译器就可以立即忘记arr
是一个数组。类似于arr[i]=6的语句代码>将被处理为内存[内存[地址\地址\地址\地址\地址\地址\地址]=6代码>。编译器不会关心是否my_array[0]
|
v
+---+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+
^
|
Address of my_array[0].