小谈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

相关文章
相关标签/搜索