【问题标题】:GCC uses the same address/pointer for `array` and `&array` in stack [duplicate]GCC 对堆栈中的`array`和`&array`使用相同的地址/指针[重复]
【发布时间】:2017-11-02 19:16:37
【问题描述】:

在一所学校,我们必须编写一个小程序,它应该查看文件的前 2 个字节,以检查它是否像 JPEG 文件一样开始。 (这是一门 UNIX 初学者课程)

一组提供了以下解决方案(删除了错误处理):

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char** argv) {

    int fd = open(argv[1], 0);
    unsigned char buffer[2];
    ssize_t readBytes = read(fd, &buffer, 2);

    if(buffer[0] == 0xFF && buffer[1] == 0xD8) {

        printf("The file starts with a JPEG header\r\n");
    } else {

        printf("The file does not start with a JPEG header\r\n");
    }
}

它编译时没有任何警告(即使使用 -Wincompatible-pointer-types)并且可以正常工作,但不是我期望的那样。

我了解到,至少在 C++ 中,数组实际上只是指向数组第一个元素的指针,而使用 array[index] 语法实际上只是 *(array+index)

所以我编译了这个版本的程序和一个,我只使用buffer,因为我希望它是数组地址,因此,read 需要什么。结果发现两个程序在反汇编后看起来完全一样。

那么这里发生了什么?我一直在和一位同事讨论这个问题,我们猜测这是因为数组实际上只是堆栈中的一些空间,它将在编译时静态分配,因此编译器将在使用 buffer[index] 的任何地方使用静态地址。因此,为了模拟在堆存储中动态分配的数组,GCC 使用buffer[0] 的地址,只要使用了buffer。但是为什么&amp;buffer 甚至是合法的语法呢?

这整件事让我很困惑,我真的很想知道这里到底发生了什么。

【问题讨论】:

  • 数组实际上只是指向数组第一个元素的指针 - 不,它不是。
  • 虽然在这种情况下您确实注意到了任何差异,但是当您编写 &amp;buffer+1 时差异会很明显,因为这将添加“数组大小的一倍”并因此指向 @987654332 @(不存在)。正如一位 C 大师向我解释的那样,与类型语义有关。 (大师,请给他解释清楚。)
  • 在 C 语言中,数组和指向数组的指针经常被混淆、混淆和误认为是相等的。我建议你阅读this post

标签: c arrays pointers gcc memory


【解决方案1】:

我了解到,至少在 C++ 中,数组实际上只是指向数组第一个元素的指针

一点也不。数组是一种不同于指针的类型。

数组的地址与其第一个元素的地址一致,并且数组隐式转换(衰减)为指向其第一个元素的指针,因此array == &amp;array[0] == array + 0

array-to-pointer decay :

存在从数组类型的左值和右值到指针类型的右值的隐式转换:它构造一个指向数组第一个元素的指针。每当数组出现在不需要数组但需要指针的上下文中时,都会使用此转换。

【讨论】:

  • 非常感谢。这绝对澄清了事情。但是&amp;buffer 不是char(*)[2] 或类似的类型吗?既然需要char*,为什么 GCC 不会对此发出警告?
  • @Link64 你是对的。
猜你喜欢
  • 2019-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-22
  • 2022-01-02
  • 1970-01-01
  • 2012-09-05
  • 2020-12-30
相关资源
最近更新 更多