2016-10-29 28 views
-2

關於C.介意你,我 C - 我會盡全力。但剛纔我遇到了這個寶石:只是打電話來投訴

// opening a file and expecting a certain size of it. 
unsigned char buf[ sizeof(sometype) ]; 
struct stat s; 
//.. open file, do fstat 
if (s.st_size != sizeof(buf)) { 
} 

而且我從GCC得到一個警告:比較有符號和無符號。所以sizeof()(gcc)返回與s.st_size(libc)不同的類型。

抱歉抱怨。我喝了幾瓶啤酒,遇到了這種情況,這簡直令人不快:它們都應該是未簽名的。

+2

's.st_size'字段的類型爲'off_t',與偏移類型兼容(for'fseek'等等),所以它被簽名,不好意思。 –

+3

雖然我同意,但這不是一個問題。 – duskwuff

+1

我投票結束這個問題作爲題外話,因爲這顯然不是一個問題。 – Jules

回答

1

這比一個C問題更一POSIX一致性問題的:

  • stat結構的st_size構件是用字節表示的文件的大小,並與其他POSIX函數鍵入off_t,出於一致性的那在文件中使用(可能爲負數)字節偏移量。
  • 這種類型是有符號的,雖然它沒有多大意義有一個負面的文件大小,負值可能表明文件大小無法計算。
  • 關於這個成員的主要問題是它的範圍:它曾經是一個32位長的文件,當文件大於2GB甚至4GB變得更常見時,這會引起頭疼。

gcc警告潛在的符號/無符號比較,因爲這種表達的語義模糊的許多人,經歷了微妙的變化,正常化的過程中,併產生潛在的違反直覺的結果。

在你的情況,我相信你也知道,你可以通過鑄造的其他參數一個擺脫了警告,但你應該提防off_tsize_t可能有不同的尺寸,他們在32位做環境,所以鑄造s.st_size(size_t)是不正確的:

if (s.st_size != (off_t)sizeof(buf)) { 
} 

你可能會認爲,off_t可能比size_t小,但它是不可能的。在任何情況下,是爲了避免投的方式,如果gcc不抱怨混合簡單算術符號和無符號表情,你可以寫:

if (s.st_size - sizeof(buf) != 0) { 
} 

最後,禁用該警告是因爲它反效果通常是關於真正問題的一個很好的暗示。通過打開大多數警告(gcc -Wall -Wclang -Weverything),使用編譯器提供的所有幫助是一個好習慣。

+0

事情是:我工作的地方,我必須用-Wall和-Wextra編譯。此外,任何演員被視爲紅旗(除了他們是醜陋的事實)。如有任何警告。所以,我一直堅持這個,在正常情況下,我不會那麼激動,但是這兩個與C本身非常接近,它只是讓我的頭髮站得很緊。爲什麼要通過簽名st_size?誰認爲這樣的設計? – KJH

+1

@KJH:'st_size'是有符號的,因爲它的類型是'off_t',它是用於文件大小的類型(與'size_t'相反,它是用於內存大小的類型,以及'sizeof'運算符產生的值);因爲'lseek()'使用'off_t'作爲新的位置,相對或絕對地以字節爲單位的當前位置,'off_t'必須是一個有符號的類型。有人可能會爭論(我會),對'lseek()'''''soff_t'會更好 - 類似於'ssize_t'和'size_t' - ,但這就是我們現在所擁有的。 –

+0

@KJH:我懷疑是這樣的。上述技巧是否在沒有警告的情況下編譯?如果在目標系統的標準頭文件中定義了它,也可以使用'ssizeof(buf)'。 – chqrlie