小談C語言中常見數據類型在32及64位機上的使用

一、概述編程

  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字節

 

在寫跨平臺的程序時,必定要注意這些基本類型的長度大小。

 

我的微博:http://weibo.com/zsxxsz

相關文章
相關標籤/搜索