小谈C语言中常见数据类型在32及64位机上的使用

本文通过实例演示了C语言中int、size_t等基本数据类型在32位与64位Linux系统上的长度差异,解释了由此引发的潜在问题,并提供了调试思路。
1、概述

  C语言有一些非常基本的数据类型,正是这些基本类型让我们可以延伸了无限的用户自定义类型,本文主要介绍了 int, size_t, time_t, long, long long int 等基本数据类型在Linux32 及 Linux64 的使用情况。表面看上去,这些类型确实太基础太简单,似乎没啥可讲的,实事似乎也是如此,用过C的对这些都已经非常熟悉了,这还用讲?在PC 64位机器出来之前,我们确实不用太关注这些,因为在32位机上编程,似乎很少出现过什么问题,但64位机出来了,象Linux 也支持64位机器,问题就来了,为什么?因为它们的长度发生了变化,而我们的程序也就有可能需要改变一下。

2、举例

先举个例子,如下:


1. #include <stdio.h>
2. #include <stdlib.h>
3.
4. static void get_length(size_t *size)
5. {
6. if (size)
7. *size = 100;
8. }
9.
10. static void test(void)
11. {
12. char *buf = strdup("hello world");
13. int n;
14.
15. printf("buf: %s\n", buf);
16. get_length((size_t*) &n);
17.
18. printf("buf: %s, n: %d\n", buf, n);
19. free(buf);
20. }
21.
22. int main(int argc, char *argv[])
23. {
24. test();
25. return (0);
26. }



首先将此程序在32位机的 Linux 上运行一下,如下:

buf: hello world

buf: hello world, n: 100

OK,如我们所料,一切正常。



  然后再将些程序在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字节才是,这便是问题的关键所在,所以在遇到此类问题时,一定得要注意基本类型在不同机器上的空间大小了。



3、小结

  以上的例子只是一个简单的例子,也许还容易看得出来,当我们的项目比较大时,这种错误可能会偶尔发生一下,那可能就是致命的了,因为有时它并不会导致程序异常退出产生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字节



在写跨平台的程序时,一定要注意这些基本类型的长度大小。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值