【发布时间】: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。但是为什么&buffer 甚至是合法的语法呢?
这整件事让我很困惑,我真的很想知道这里到底发生了什么。
【问题讨论】:
-
数组实际上只是指向数组第一个元素的指针 - 不,它不是。
-
虽然在这种情况下您确实注意到了任何差异,但是当您编写
&buffer+1时差异会很明显,因为这将添加“数组大小的一倍”并因此指向 @987654332 @(不存在)。正如一位 C 大师向我解释的那样,与类型语义有关。 (大师,请给他解释清楚。) -
在 C 语言中,数组和指向数组的指针经常被混淆、混淆和误认为是相等的。我建议你阅读this post
标签: c arrays pointers gcc memory