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