指针算术 - 数组和指向数组的指针的问题
Pointer Arithmetic - Issues with array and pointer to an array
我最近切换到 C 并试图找出指针。
#include <stdio.h>
int main()
{
int arr[5] = {1,2,3,4,5};
int *a = &arr;
printf("Array : %p\n", arr);
for(int i=0; i<5; i++)
{
printf("Value and Address of Element - %d : %d\t%p,\n", i+1, arr[i], &arr[i]);
}
printf("Pointer to the Array : %p\n", a);
printf("Value pointed by the pointer : %d\n", *a);
a = (&a+1);
printf("Pointer after incrementing : %p\n", a);
return 0;
}
但是,下面这行似乎不起作用。
a = (&a+1);
打印指针a的增量值后,它仍然指向数组(arr)。
这是程序的输出:
Array : 0x7ffe74e5d390
Value and Address of Element - 1 : 1 0x7ffe74e5d390,
Value and Address of Element - 2 : 2 0x7ffe74e5d394,
Value and Address of Element - 3 : 3 0x7ffe74e5d398,
Value and Address of Element - 4 : 4 0x7ffe74e5d39c,
Value and Address of Element - 5 : 5 0x7ffe74e5d3a0,
Pointer to the Array : 0x7ffe74e5d390
Value pointed by the pointer : 1
Pointer after incrementing : 0x7ffe74e5d390
如您所见,指针 'a' 仍然指向第一个元素。但是,理论上 'a' 不应该指向最后一个元素之后的任何内容(假设 &a + 1 将指针递增整个数组的大小 - 来源:difference between a+1 and &a+1)
有人可以解释为什么吗?
在这种特殊情况下,变量和数组可以像下面这样放置在堆栈上,标准不保证这一点。每个单元格都是整数。你还记得每次放置局部变量时堆栈地址都会减少吗?
+-+-+-+-+-+-+
|a|1|2|3|4|5|
+-+-+-+-+-+-+
&a+1
,不是数组的地址,你取a的地址,往前移动一个单元格,结果就是数组的地址。
a = (&a+1);
设置 a
指向 a
.
地址之外的一个“东西”
之前,您的代码使用 int *a = &arr;
将 a
设置为 &arr
。 (这违反了标准 C 约束,因为 &arr
的类型是指向数组的指针,而不是指向 int
的指针。正确的定义是 int *a = arr;
。)我怀疑你的意图a = (&a+1);
是将 a
设置为指向一个超出当前指向的位置。但是,正确的代码是 a = a+1;
。它将 a
的 value 加一,并将结果赋给 a
。
相反,a = (&a+1);
使用 a
的地址而不是它的值。
这导致 a
指向内存中 a
之外的一个。在您的实验中,似乎数组 arr
碰巧在那里,并且您的 C 实现相应地表现。
(这解释了您观察到的结果,但这不是您应该依赖的行为。C 标准没有定义当您以这种方式滥用指针时会发生什么,包括编译器优化在内的各种事情都可能导致程序表现得好像 &a+1
没有指向 arr
,即使 arr
实际上位于内存中的地址 &a+1
。)
我最近切换到 C 并试图找出指针。
#include <stdio.h>
int main()
{
int arr[5] = {1,2,3,4,5};
int *a = &arr;
printf("Array : %p\n", arr);
for(int i=0; i<5; i++)
{
printf("Value and Address of Element - %d : %d\t%p,\n", i+1, arr[i], &arr[i]);
}
printf("Pointer to the Array : %p\n", a);
printf("Value pointed by the pointer : %d\n", *a);
a = (&a+1);
printf("Pointer after incrementing : %p\n", a);
return 0;
}
但是,下面这行似乎不起作用。
a = (&a+1);
打印指针a的增量值后,它仍然指向数组(arr)。 这是程序的输出:
Array : 0x7ffe74e5d390
Value and Address of Element - 1 : 1 0x7ffe74e5d390,
Value and Address of Element - 2 : 2 0x7ffe74e5d394,
Value and Address of Element - 3 : 3 0x7ffe74e5d398,
Value and Address of Element - 4 : 4 0x7ffe74e5d39c,
Value and Address of Element - 5 : 5 0x7ffe74e5d3a0,
Pointer to the Array : 0x7ffe74e5d390
Value pointed by the pointer : 1
Pointer after incrementing : 0x7ffe74e5d390
如您所见,指针 'a' 仍然指向第一个元素。但是,理论上 'a' 不应该指向最后一个元素之后的任何内容(假设 &a + 1 将指针递增整个数组的大小 - 来源:difference between a+1 and &a+1)
有人可以解释为什么吗?
在这种特殊情况下,变量和数组可以像下面这样放置在堆栈上,标准不保证这一点。每个单元格都是整数。你还记得每次放置局部变量时堆栈地址都会减少吗?
+-+-+-+-+-+-+
|a|1|2|3|4|5|
+-+-+-+-+-+-+
&a+1
,不是数组的地址,你取a的地址,往前移动一个单元格,结果就是数组的地址。
a = (&a+1);
设置 a
指向 a
.
之前,您的代码使用 int *a = &arr;
将 a
设置为 &arr
。 (这违反了标准 C 约束,因为 &arr
的类型是指向数组的指针,而不是指向 int
的指针。正确的定义是 int *a = arr;
。)我怀疑你的意图a = (&a+1);
是将 a
设置为指向一个超出当前指向的位置。但是,正确的代码是 a = a+1;
。它将 a
的 value 加一,并将结果赋给 a
。
相反,a = (&a+1);
使用 a
的地址而不是它的值。
这导致 a
指向内存中 a
之外的一个。在您的实验中,似乎数组 arr
碰巧在那里,并且您的 C 实现相应地表现。
(这解释了您观察到的结果,但这不是您应该依赖的行为。C 标准没有定义当您以这种方式滥用指针时会发生什么,包括编译器优化在内的各种事情都可能导致程序表现得好像 &a+1
没有指向 arr
,即使 arr
实际上位于内存中的地址 &a+1
。)