16

我是一门编程入门课程的助教,有同学犯了这样的错误:

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.

4

5 回答 5

26

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

| int | int | ... | int |

当您将一元运算&符应用于数组时,您将获得数组的地址。就像你把它应用到其他东西上一样,真的。&test指向 50 块的指针也是如此ints

(&test) -----------> | int | int | ... | int |

指向 50 个整数数组的指针具有类型int (*)[50]——即&test.

当您只在它不是单元运算符或一元运算符test的操作数的任何地方使用名称时,它会被评估为指向其第一个元素的指针。因此,您传递给的 将评估为指向元素的指针:sizeof&testfoo()test[0]

(test) -----------------\
                        v
(&test) -----------> | int | int | ... | int |

您可以看到它们都指向相同的地址 - 尽管&test指向整个数组,并且test指向数组的第一个元素(仅显示在这些值所具有的不同类型中)。

于 2010-05-24T00:11:10.113 回答
10

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

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

于 2010-05-23T23:25:10.700 回答
6

如果您定义一个数组,例如

char name[20];

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

检查地址(&name + 1)。它&name的 形式不同sizeof(char [20])

于 2010-05-24T00:00:45.973 回答
2

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

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

array,当转换为指向其初始元素的指针时,类型为T *。的类型&arrayT (*)[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
于 2010-05-24T00:07:12.203 回答
-3

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

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

因此,根据这&test 可能会有所不同,test但 gcc 会对此进行优化,因为此时没有额外的间接级别。

于 2010-05-23T23:58:14.237 回答