uint8_t / uint16_t / uint32_t /uint64_t 是什么數據類型?
在nesc的代碼中,你會看到很多你不認識的數據類型,比如uint8_t等。咋一看,好像是個新的數據類型,不過C語言(nesc是C的擴展)里面好像沒有這種數據類型啊!怎么又是u又是_t的?很多人有這樣的疑問。論壇上就有人問:以*_t結尾的類型是不是都是long型的?在baidu上查一下,才找到答案,這時才發覺原來自己對C掌握的太少。
那么_t的意思到底表示什么?具體的官方答案沒有找到,不過我覺得有個答案比較接近。它就是一個結構的標注,可以理解為type/typedef的縮寫,表示它是通過typedef定義的,而不是其它數據類型。
uint8_t,uint16_t,uint32_t等都不是什么新的數據類型,它們只是使用typedef給類型起的別名,新瓶裝老酒的把戲。不過,不要小看了typedef,它對於你代碼的維護會有很好的作用。比如C中沒有bool,於是在一個軟件中,一些程序員使用int,一些程序員使用short,會比較混亂,最好就是用一個typedef來定義,如:
typedef char bool;
一般來說,一個C的工程中一定要做一些這方面的工作,因為你會涉及到跨平台,不同的平台會有不同的字長,所以利用預編譯和typedef可以讓你最有效的維護你的代碼。為了用戶的方便,C99標准的C語言硬件為我們定義了這些類型,我們放心使用就可以了。 按照posix標准,一般整形對應的*_t類型為:
1字節 uint8_t
2字節 uint16_t
4字節 uint32_t
8字節 uint64_t
這些數據類型是 C99 中定義的,具體定義在:/usr/include/stdint.h ISO C99: 7.18 Integer types <stdint.h>
/* There is some amount of overlap with <sys/types.h> as known by inet code */
#ifndef __int8_t_defined
# define __int8_t_defined
typedef signed char int8_t;
typedef short int int16_t;
typedef int int32_t;
# if __WORDSIZE == 64
typedef long int int64_t;
# else
__extension__
typedef long long int int64_t;
# endif
#endif
/* Unsigned. */
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
#ifndef __uint32_t_defined
typedef unsigned int uint32_t;
# define __uint32_t_defined
#endif
#if __WORDSIZE == 64
typedef unsigned long int uint64_t;
#else
__extension__
typedef unsigned long long int uint64_t;
#endif
注意:
必須小心 uint8_t 類型變量的輸出,例如如下代碼,會輸出什么呢?
uint8_t fieldID = 67;
cerr<< "field=" << fieldID <<endl;
結果發現是:field=C 而 不是我們所想的 field=67
這是由於:
typedef unsigned char uint8_t;
uint8_t 實際是一個 char, cerr << 會輸出 ASCII 碼是 67 的字符,而不是 67 這個數字.
因此,輸出 uint8_t 類型的變量實際輸出的是其對應的字符, 而不是真實數字.
若要輸出 67,則可以這樣:
cerr<< "field=" << (uint16_t) fieldID <<endl;
結果是:field=67
同樣: uint8_t 類型變量轉化為字符串以及字符串轉化為 uint8_t 類型變量都要注意, uint8_t類型變量轉化為字符串時得到的會是ASCII碼對應的字符, 字符串轉化為 uint8_t 變量時, 會將字符串的第一個字符賦值給變量.
例如如下代碼:
#include <iostream>
#include <stdint.h>
#include <sstream>
using namespace std;
int main()
{
uint8_t fieldID = 67;
// uint8_t --> string
string s;
ostringstream strOStream;
strOStream << fieldID;
s = strOStream.str();
cerr << s << endl;
// string --> uint8_t
s = "65";
stringstream strStream;
strStream << s;
strStream >> fieldID;
strStream.clear();
cerr << fieldID << endl;
}
上述代碼輸出的是:
C
6