2017-06-01 75 views
0

array`在一所學校,我們不得不寫一個小程序,那應該看看第2個字節的文件,以檢查它是否像開始一個JPEG文件應該與否。 (這是一個UNIX初級課程)GCC使用相同的地址/指針`array`和`&堆棧

一組提供了以下解決方案(刪除錯誤處理):

#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指針類型)和作品,因爲它應該,但不是我期望的。

我瞭解到,在C++中至少一個數組其實只是一個指向數組的第一個元素,並使用array[index]語法實際上只是*(array+index)

所以我編這個版本的程序和一個,我只是使用buffer,因爲我期望它是陣列地址,因此,什麼read要求。原來這兩個程序在拆解時看起來完全一樣。

那麼這裏發生了什麼?我一直在和一個同事討論這個問題,我們猜測這是因爲數組實際上只是堆棧中的一些空間,在編譯期間會被靜態分配,所以編譯器會在使用buffer[index]的地方使用靜態地址。因此,要模擬在堆存儲中動態分配的陣列,只要使用buffer,GCC就會使用地址爲buffer[0]。但爲什麼&buffer甚至會成爲法律語法?

這整個事情真的讓我困惑,我真的很想知道究竟是怎樣發生在這裏。

+4

*陣列實際上只是一個指向數組的第一個元素* - 不,事實並非如此。 –

+0

儘管在這種情況下你會注意到任何差異,當你寫'&buffer + 1'時,這個差別會很明顯,因爲這會增加「一次數組的大小」,並因此指向'buffer [3]'(這不存在)。與C語言大師解釋我一樣,與類型語義有關。 (大師,請解釋一下這個更好。) –

+0

在C中,一個數組和一個指向數組的指針經常被混淆,混淆和誤認爲是平等的。我建議你閱讀[這篇文章](https://stackoverflow.com/questions/1461432/what-is-array-decaying/1461449#1461449) – Badda

回答

1

我明白了,在C++中至少一個陣列實際上只是一個指向數組

一點也不的第一個元素。數組是一種與指針不同的類型。

數組地址與其第一個元素的地址相符,數組隱式轉換(衰減)到指向其第一個元素的指針,因此爲array == &array[0] == array + 0

參見array-to-pointer decay

有從左值和數組類型的右值到指針類型的右值的隱式轉換:它構造的指針數組的第一個元素。只要數組出現在不需要數組的情況下,就會使用此轉換,但指針是。

+0

非常感謝。這絕對清除了事情。但不是'char(*)[2]''類型的'&buffer'或類似的東西呢?爲什麼GCC不會對此提出警告,因爲需要char *'? – Link64

+0

@ Link64你是對的。 –