Array变量是否指向自身?

时间:2012-02-03 17:29:11

标签: c++ c arrays pointers binding

我尝试了一些代码来检查数组和指针的行为。其内容如下。

#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)中的所有信息都是在运行时存储的?

4 个答案:

答案 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代表一个地址; *ss[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;

哪不是。