一、概述編程
C語言有一些很是基本的數據類型,正是這些基本類型讓咱們能夠延伸了無限的用戶自定義類型,本文主要介紹了 int, size_t, time_t, long, long long int 等基本數據類型在Linux32 及 Linux64 的使用狀況。表面看上去,這些類型確實太基礎太簡單,彷佛沒啥可講的,實事彷佛也是如此,用過C的對這些都已經很是熟悉了,這還用講?在PC 64位機器出來以前,咱們確實不用太關注這些,由於在32位機上編程,彷佛不多出現過什麼問題,但64位機出來了,象Linux 也支持64位機器,問題就來了,爲何?由於它們的長度發生了變化,而咱們的程序也就有可能須要改變一下。指針
二、舉例調試
先舉個例子,以下:code
#include <stdio.h> #include <stdlib.h> static void get_length(size_t *size) { if (size) *size = 100; } static void test(void) { char *buf = strdup("hello world"); int n; printf("buf: %s\n", buf); get_length((size_t*) &n); printf("buf: %s, n: %d\n", buf, n); free(buf); } int main(int argc, char *argv[]) { test(); return (0); }
首先將此程序在32位機的 Linux 上運行一下,以下:內存
buf: hello worldget
buf: hello world, n: 100it
OK,如咱們所料,一切正常。io
而後再將些程序在64位機的 Linux 上運行一下,以下:微博
buf: hello world編譯
buf: (null), n: 100
奇怪的現象出來了,怎麼printf出的結果爲空呢?暈菜,爲啥通過 get_length()/1 後世界改變了,buf 的內容沒有了,被指向一個空指針,而 buf 明明是尚未被釋放呀。趕快用 valgrind 檢查一下,
valgrind --tool=memcheck --leak-check=yes --show-reachable=yes ./a.out
「2 bytes in 1 blocks are definitely lost in loss record 1 of 1」,說有塊內存未被釋放,而在 test() 後面確實釋放過 buf 呀,誰偷偷地給釋放了而沒有告訴俺?更暈菜,難道是 libc 的問題?再用 valgrind 在32位機檢查一下,一切OK,沒有出現64位機上的錯誤提示,說明內存確實由 test() 中的 free(buf) 釋放了。
正當對此問題百思不解時,突然想到一個問題 int * 至 size_t* 類型轉換會不會有問題?由於 size_t 在32位機上是4字節,而在64位機上是8字節,int在32位及64位機上都是4字節,嗯,問題就在於此,再回頭仔細看看上述代碼,在 test() 中將 &n 由 int * 強制轉換成 size_t *, 這樣能夠避免編譯警告,但在 get_length()/1 中呢?它是不會知道 size_t *size 中 size 所指空間是4字節的,而依然當8字節對待,這樣在對 *size = 100 進行賦值時就發生了改變,size 所指的8字節空間發生改變,而實際應該只改變4字節纔是,這即是問題的關鍵所在,因此在遇到此類問題時,必定得要注意基本類型在不一樣機器上的空間大小了。
三、小結
以上的例子只是一個簡單的例子,也許還容易看得出來,當咱們的項目比較大時,這種錯誤可能會偶爾發生一下,那可能就是致命的了,由於有時它並不會致使程序 異常退出產生core文件,但卻會改變咱們的運行結果,本人就所以問題調試了兩天多的時間才找到緣由,另外,即便所以問題產生了 core 文件,你會發現用 gdb 調試該 core 時根本找不到緣由所在。
下面列出一些基本類型在32位及64位機上的大小差別
int | long | size_t | time_t | long long int | |
32位機器 | 4字節 | 4字節 | 4字節 | 4字節 | 8字節 |
64位機器 | 4字節 | 8字節 | 8字節 | 8字節 | 8字節 |
在寫跨平臺的程序時,必定要注意這些基本類型的長度大小。