“地址”(&)被忽略的数组/地址是gcc吗?

时间:2010-05-23 23:19:46

标签: c gcc pointers addressof

我是入门编程课程的助教,有些学生犯了这种错误:

char name[20];
scanf("%s",&name);

这并不奇怪,因为他们正在学习......令人惊讶的是,除了gcc警告之外,代码也起作用(至少这部分)。我一直在努力理解,并编写了以下代码:

void foo(int *v1, int *v2) {
  if (v1 == v2)
    printf("Both pointers are the same\n");
  else
    printf("They are not the same\n");
}

int main() {
  int test[50];
  foo(&test, test);
  if (&test == test)
    printf("Both pointers are the same\n");
  else
    printf("They are not the same\n");
}

编译并执行:

$ gcc test.c -g
test.c: In function ‘main’:
test.c:12: warning: passing argument 1 of ‘foo’ from incompatible pointer type
test.c:13: warning: comparison of distinct pointer types lacks a cast
$ ./a.out 
Both pointers are the same
Both pointers are the same

有谁可以解释为什么他们没有什么不同?

我怀疑是因为我无法获取数组的地址(因为我不能拥有& &x),但在这种情况下,代码不应该编译。

编辑:我知道数组本身与第一个元素的地址相同,但我认为这与此问题无关。例如:

int main() {
  int a[50];
  int * p = a;
  printf("%d %d %d\n", p == a, p == &a[0], &p[0] == a);
  printf("%d %d %d\n", p == &a, &p == a, &p == &a);
}

打印:

$ ./a.out 
1 1 1
1 0 0

我不明白为什么第二行以1开头。

5 个答案:

答案 0 :(得分:23)

在您的示例中,数组test是一个50 ints的块。所以它看起来像这样:

| int | int | ... | int |

将一元&运算符应用于数组时,您将获得数组的地址 。就像你将它应用于其他任何东西一样,真的。因此&test是一个指向50 ints

块的指针
(&test) -----------> | int | int | ... | int |

指向50个整数数组的指针的类型为int (*)[50] - 这是&test的类型。

当您在任何不是test或一元 - sizeof运算符的操作数的地方使用名称&时,会将其评估为指向其第一个元素的指针。因此,传递给test的{​​{1}}会计算为指向foo()元素的指针:

test[0]

你可以看到这两个都指向同一个地址 - 尽管(test) -----------------\ v (&test) -----------> | int | int | ... | int | 指向整个数组,&test指向数组的第一个元素(仅显示在这些值具有的不同类型

答案 1 :(得分:9)

实际上,它们是不同的,它们至少没有相同的类型。

但是在C中,数组的地址与地址相同 数组中的第一个元素就是“它们没有区别”的原因,基本上,它们指向同一个东西。

答案 2 :(得分:5)

如果您定义类似

的数组
char name[20];

name可隐式转换为char*,但&name的类型为char (*)[20](指向20个字符数组的指针)。地址是一样的。

检查(&name + 1)的地址。它与&name的{​​{1}}不同。

答案 3 :(得分:2)

数组的名称,在大多数情况下,计算为其初始元素的地址。两个例外是它是sizeof或一元&的操作数。

一元&给出了其参数的地址。数组的地址与其初始元素的地址相同,因此(void*)&array == (void*)array将始终为真。

array在转换为指向其初始元素的指针时,其类型为T *&array的类型为T (*)[n],其中n是数组中元素的数量。因此,

int* p = array;        // Works; p is a pointer to array[0]
int* q = &array;       // Doesn't work; &array has type int (*)[10]
int (*r)[10] = &array; // Works; r is a pointer to array

答案 4 :(得分:-2)

我相信这是一个gcc优化。想一想。

  • &test指向test
  • 的地址
  • test指向test&test[0]
  • 的第一个元素
  • [0]*
  • 相同(大部分)

所以根据这个&test 可以test不同,但是gcc会优化它,因为在这一点上没有额外的间接级别的目的。