常见数据类型大小的总结

C 中变量为什么需要被指定类型?

  1. 变量的类型告诉编译器怎么处理这个变量的数据,指针加法运算
  2. 变量的类型告诉编译器要分配多少内存空间

数据类型特别是int相关的类型在不同位数机器的平台下长度不同。C99 标准并不规定具体数据类型的长度大小,只规定级别。什么是级别?比如int的大小不能超过long

还有什么是字(word)

字的大小等于 CPU 指令大小,即代表一次处理信息的能力 = 系统位,计算机从 32 位发展到 64 位的原因是寻址空间不足。

常见基本数据类型的大小

16位 32位 64位
char 1 1 1
short 2 2 2
int 等于 unsigned int 4 4 4
long 4 4 8
long long / 8 8
float / 4 4
double / 4 8
pointer 2 4 8
size_t 2 4 8
unsigned signed
8位(1字节) 0 ~ 255 -128 ~ 127
16位(2字节) 0~65534 -32767~32766
32位(4字节) 0~4294967294 -2147483647~2147483646
64位(8字节) 0~1844亿亿1.8 x 10^19 dead

这两个表值得记住!

查看地址的方法

  • %d将所给存储单元以十进制有符号型形式输出
  • %p将所给存储单元以十六进制输出指针变量对应的地址值
  • %x将所给存储单元以十六进制形式输出

为什么 64 位系统的地址在 C 语言中打印出来还是 32 位的呢?

查看地址用%p参数进行格式化,不然即使是 long 也同样的是被阉割成 32 位的,具体原因可能跟历史有关吧。(图中上半部分是%x的打印结果;在 64 位系统下,地址的长度为 48 位,且以7FFF为前缀的地址都是属于内存中的某块区域)

float & double 的存储形式

float:

double:

转换公式:

浮点数的二进制表示

size_t 类型

int 小于等于数据线宽度,size_t 大于等于地址线宽度。

From 知乎:size_t 存在的最大原因可能是地址线宽度历史中经常都是大于数据线宽度的。在数据只有 8 位的年代,地址率先进入 10 位、12 位;在数据 16 位的年代,地址也已经进入了 20 位,24 位。目前的 int 普遍是 32 位,而 size_t 在主流平台中都是 64 位。size_t 为什么存在?因为无论 int 还是 unsigned int 都很可能小于 size_t 需要的大小,所以必须有个 size_t。

这个名字很直观,是sizeof (type)的返回类型,就是表示一个 size。你说用 unsigned int 来替换,考虑如果你的代码在I16LP32平台下运行(比如第一代摩托罗拉68000),那就捉急了吧?

为了跨平台,为了能保存足够大的非负整数,比如数组下标。

size_t 定义在标准头文件 中,是一个 unsigned 整型。C 的标准库这么做是为了代码的可移植性。不同的编译器,sizeof、strlen() 有不同的返回类型,用 size_t 可以在所有的标准 C 语言中提高代码的包容性。

  1. sizeof:获取操作数占用的内存空间字节数,返回类型 size_t。
  2. strlen:获取字符数组实际使用的字节数,不包含数组结尾符'\0',返回类型 size_t。

我的电脑上:sizeof(size_t)等于 8,相当于 unsigned long。

size_t 与 unsigned int 的区别

size_t 和 unsigned int 有所不同,size_t 的取值范围是目标平台下最大可能的数组尺寸。一些平台下 size_t 的范围小于 int 的正数范围,又或者大于 unsigned int。

最典型的,在 x64 下,unsigned int 还是 4,但 size_t 是 8。这意味着你在 x64 下最大可能开辟的数组尺寸是 $2^{64}$。如果你使用 int 或者 unsigned int,那么在 x64 下如果你的代码中全部使用它们作为数组的尺寸标记,那么你就会失去控制 $2^{32}$ 尺寸以上的数组的机会。虽然现在在 x64 上开辟一个大于 $2^{32}$ 大小的连续数组依然是个不大可能的事情,不符合实际需求,但是…… ↓↓↓

“640K 内存对于任何人来说都足够了。” —— 比尔盖茨

参考

忘了保存。。。(打了自己一巴掌)

0%