在学校中,我们必须编写一个小程序,该程序应该查看文件的前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 headerrn");
} else {
printf("The file does not start with a JPEG headerrn");
}
}
它没有任何警告(即使使用-WiNCAPTIBL-POINTER-TYPES(进行编译,并且可以根据自己的期望进行工作。
我了解到,至少在C 中,数组实际上只是指向数组的第一个元素的指针,而使用array[index]
语法实际上只是*(array+index)
因此,我编制了该版本的程序,也编写了一个,其中我只使用buffer
,因为我希望它是数组地址,因此read
所需的内容。事实证明,拆卸时两个程序看起来完全相同。
那是怎么回事?我一直在与同事讨论这个问题,我们猜这是因为该数组实际上只是堆栈中的一些空间,在编译时间内将静态分配,因此编译器将在使用buffer[index]
的任何地方使用静态地址。因此,为了模拟在堆存储中动态分配的数组,GCC使用buffer[0]
的地址使用CC_6。但是,为什么&buffer
甚至是法律语法?
这整个事情确实使我感到困惑,我真的很想知道这里实际发生了什么。
我了解到,至少在C 中,数组实际上只是指向数组的第一个元素
的指针
一点也不。阵列是一种与指针不同的类型。
数组的地址与其第一个元素的地址一致,并且数组将(衰减(隐式转换为指针到其第一个元素,因此array == &array[0] == array + 0
。
请参阅阵列到点衰减:
lvalues和数组类型的rvalues有一个隐式转换到指针类型的rvalues:它构造了指向数组的第一个元素的指针。每当数组出现在不预期的上下文中,而是指向指针。
时,都会使用此转换。