GCC在堆栈中对`array`和`& array`使用相同的地址/指针

时间:2017-06-01 14:56:44

标签: c arrays pointers gcc memory

在学校,我们必须编写一个小程序,它应该查看文件的前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。但为什么&buffer甚至会成为合法的语法?

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

1 个答案:

答案 0 :(得分:1)

  

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

完全没有。数组是一种与指针不同的类型。

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

请参阅array-to-pointer decay

  

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