Array变量是否指向自身?
我尝试了一些代码来检查数组和指针的行为。 其内容如下。
#include main(){ int s[]={1,2}; int *b=s; printf("%d, %d, %d\n", s, &s, *s); printf("%d, %d, %d\n", b ,&b, *b); }
最初我认为指针和数组是相同的但是…
令我惊讶的是,’s’和’&s’的价值与’b’不同。 这是否意味着一个数组变量“指向自己?”
我现在也对实际上变量“名称”感到困惑? 如何与内存中的位置进行绑定? 我只是无法想象那里发生的事情! 内存(RAM)中的所有信息都是在运行时存储的?
除非它是sizeof
或一元&
运算符的操作数,或者是用于初始化声明中的另一个数组的字符串文字,否则“N元素数组T
”的表达式将替换为类型“的表达式”指向T
“的指针,表达式的值将是数组中第一个元素的地址。
假设以下代码:
int arr[10]; foo(arr);
在对函数foo
的调用中,表达式arr
从类型“10-element array of int
”转换为“指向int
”,而arr
的第一个元素的地址实际上是传递给foo
。
我们将foo
定义为
void foo(int a[]) {}
要么
void foo(int *a) {}
在函数参数声明的上下文中, T a[]
和T a[N]
与T *a
相同; 参数是指针类型,而不是数组类型。 请注意,这仅适用于函数参数声明。
如上所述,此规则的一个例外是当数组表达式是一元&
运算符的操作数时。 如果我们将对foo
的调用更改为read
foo(&arr);
那么表达式&arr
的类型是“指向10个元素的int
数组”,或者是int (*)[10]
,表达式的值是a的地址。 为此, foo
的定义是
void foo(int (*a)[10]) {}
在C中, 数组的地址和数组的第一个元素的地址是相同的 – 因此表达式arr
和&arr
都具有相同的值 ,但它们的类型是不同的。 这对涉及指针运算的操作很重要。 例如,假设我们的代码已经编写完成
int arr[10]; foo(arr); ... void foo(int *a) { ... a++; ... }
进入时,指向arr[0]
。 表达式a++
会使指针前进指向数组中的下一个整数( arr[1]
)。
现在假设代码已写为
int arr[10]; foo(&arr); ... void foo(int (*a)[10]) { ... a++; ... }
在进入时,仍然指向arr[0]
(记住,数组的地址与数组的第一个元素的地址相同),但这次表达式a++
将使指针前进指向下一个10 -element整数数组 ; 而不是推进指针sizeof (int)
字节,我们推进sizeof (int[10])
字节。
所以这就是为什么在你的printf
语句中你会看到s
和&s
的相同值 。 您应该使用%p
转换说明符来打印指针值,并且它期望相应的参数为void *
类型,因此将这些printf
语句更改为
printf("%p %p %d\n", (void *) s, (void *) &s, *s); printf("%p %p %d\n", (void *) b, (void *) &b, *b);
好吧,让我们说以下是执行时内存的外观
int s[]={1,2}; int *b=s; s[] +-----+-----+ | 1 | 2 | +-----+-----+ 100 104 ^ | | int *b = &s +-----+ | 100 | +-----+ 200
s
是一个数组。 这意味着,它是一个与变量s
相关联的连续内存位置,并且通过偏移数组变量名来访问每个元素。
因此,当你使用s
它实际上归结为数组的地址(在这种情况下为100
)。 当你做*s
,它归结为*(s+0)
,相当于s[0]
,所以*s
代表存储在第零位置的内容(在这种情况下, s[0]
为1
)。 什么时候做&s
,这将打印&s
的地址s (which is
在这种情况下s (which is
100`)。
注意,这里s
和&s
代表一个地址; *s
和s[x]
表示整数。
这同样适用于指针。 因此, b
打印它所拥有的内容,即s
的地址(在这种情况下为100
)。 &b
打印&b
的地址,在这种情况下为200
。 并且, *b
打印数组s
的第一个元素的内容,即1
。
我修改了你的程序,让它打印地址。
#include int main(void) { int s[]={1,2}; int *b=s; printf("%p, %p, %d\n", (void *)s, (void *)&s, *s); printf("%p, %p, %d\n", (void *)b, (void *)&b, *b); return 0; }
输出:
0xbfc4f3e4, 0xbfc4f3e4, 1 0xbfc4f3e4, 0xbfc4f3ec, 1
编辑: %p
期望void *
。 添加相同!
当数组用作函数的参数时,它会衰减为指向其第一个元素的指针。 类似地,获取数组的地址会产生指向第一个元素位置的指针(但具有不同的类型)。
至于你的第二个问题,变量名只存在于编译时。 它通常在运行时没有内存中的表示。
考虑这个的一个简单方法是作为指针的数组不能通过赋值来改变,它实际上是指向已知内存量的常量指针。
要尝试,请使用:
myptr = myarray;
哪个完全没问题,然后尝试:
myarray = myptr;
哪个不是。