jump to navigation

c-faq review and a chinese translation (1.1) January 18, 2007

Posted by TSAI HONG-BIN in Programming.

Please refer to http://c-faq.com/decl/inttypes.html

Question 1.1

How do you decide which integer type to use?
If you might need large values (above 32,767 or below -32,767), use long. Otherwise, if space is very important (i.e. if there are large arrays or many structures), use short. Otherwise, use int. If well-defined overflow characteristics are important and negative values are not, or if you want to steer clear of sign-extension problems when manipulating bits or bytes, use one of the corresponding unsigned types. (Beware when mixing signed and unsigned values in expressions, though.)

Although character types (especially unsigned char) can be used as “tiny” integers, doing so is sometimes more trouble than it’s worth, due to unpredictable sign extension and increased code size. (Using unsigned char can help; see question 12.1 for a related problem.)

A similar space/time tradeoff applies when deciding between float and double. (Many compilers still convert all float values to double during expression evaluation.) None of the above rules apply if pointers to the variable must have a particular type.

Variables referring to certain kinds of data, such as sizes of objects in memory, can and should used predefined abstract types such as size_t.

It’s often incorrectly assumed that C’s types are defined to have certain, exact sizes. In fact, what’s guaranteed is that:

  • type char can hold values up to 127;
  • types short int and int can hold values up to 32,767; and
  • type long int can hold values up to 2,147,483,647.
  • something like the relation
  • sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)holds. [footnote]

From these values, it can be inferred that char is at least 8 bits, short int and int are at least 16 bits, and long int is at least 32 bits. (The signed and unsigned versions of each type are guaranteed to have the same size.) Under ANSI C, the maximum and minimum values for a particular machine can be found in the header file <limits.h>; here is a summary:

Base type Minimum size (bits) Minimum value (signed) Maximum value (signed) Maximum value (unsigned)
char 8 -127 127 255
short 16 -32,767 32,767 65,535
int 16 -32,767 32,767 65,535
long 32 -2,147,483,647 2,147,483,647 4,294,967,295

(These values are the minimums guaranteed by the Standard. Many implementations allow larger values, but portable programs shouldn’t depend on it.)If for some reason you need to declare something with an exact size (usually the only good reason for doing so is when attempting to conform to some externally-imposed storage layout, but see question 20.5), be sure to encapsulate the choice behind an appropriate typedef, but see question 1.3.

If you need to manipulate huge values, larger than the guaranteed range of C’s built-in types, you need an arbitrary-precision (or “multiple precision”) arithmetic library; see question 18.15d.

References: K&R1 Sec. 2.2 p. 34
K&R2 Sec. 2.2 p. 36, Sec. A4.2 pp. 195-6, Sec. B11 p. 257
ISO Sec., Sec.
H&S Secs. 5.1,5.2 pp. 110-114

如果你需要使用較大的數字 (大於 32,767 或小於 -32,767),用 long。若空間的使用很重要 (亦即,有大型的陣列或資料結構),用 short。其他的情況,用 int。若溢位處理很重要而且想避開關係符號,或者在處理位元或位元組時想忽略正負號,可以加上 unsigned。請小心 signed 和 unsigned 混用的情況。

雖然字元型態 (特別是 unsigned char) 可以當做 tiny integer 使用,這樣的做法有時造成的問題比好處還多,因為會有無可預期的溢位或程式規模增大 (使 integer 超過 tiny 的長度) 的問題會發生(Using unsigned char can help; see question 12.1 for a related problem.)

類似的空間/時間拉鋸也會發生在決定使用 float 還是 double 的時候。 (許多編譯器仍然會在 expression evaluation 時將所有的 float 值轉換為 double) 不過上述規則在指標所指到的變數必須有特定型態時不適用。

某些資料種類的變數,如記憶體中的物件大小,應該被預先定義 abstract types size_t

通常假設 C 的型態被定義為某種固定的大小是錯的。事實上,可以確定的只有

  • char 可表達的數最大到 127
  • short int int 可以表達到 32,767
  • long int 則可以表達到 2,147,483,647
  • 這些型態彼此間的關係可以表示為
  • · sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)

從這些值來看,可以推定 char 至少 8 bitsshort int int 至少 16 bitslong int 至少 32 bits(不論是否有正負號都是一樣大小)。在ANSI C的規範裡,一台機器的最大值和最小值可以在 header <limits.h>被找到。

如果為了某些原因你必須在宣告時給定明確的大小 (通常這麼做最好的理由,只是為了符合外掛的儲存裝置) 一定要確定將不同大小的選擇封裝進適當的 typedef

如果你需要使用非常大的數字,大過任何一個C語言所支援的資料型態,則你會需要一個任意精準度 (或多精度) 的運算函式庫。



No comments yet — be the first.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: