“C变量类型的大小取决于机器。”这是真的吗? 已签名和未签名的号码;

我被告知C类型取决于机器。 今天我想validation它。

void legacyTypes() { /* character types */ char k_char = 'a'; //Signedness --> signed & unsigned signed char k_char_s = 'a'; unsigned char k_char_u = 'a'; /* integer types */ int k_int = 1; /* Same as "signed int" */ //Signedness --> signed & unsigned signed int k_int_s = -2; unsigned int k_int_u = 3; //Size --> short, _____, long, long long short int k_s_int = 4; long int k_l_int = 5; long long int k_ll_int = 6; /* real number types */ float k_float = 7; double k_double = 8; } 

我使用minGW C编译器在32位机器上编译它

 _legacyTypes: pushl %ebp movl %esp, %ebp subl $48, %esp movb $97, -1(%ebp) # char movb $97, -2(%ebp) # signed char movb $97, -3(%ebp) # unsigned char movl $1, -8(%ebp) # int movl $-2, -12(%ebp)# signed int movl $3, -16(%ebp) # unsigned int movw $4, -18(%ebp) # short int movl $5, -24(%ebp) # long int movl $6, -32(%ebp) # long long int movl $0, -28(%ebp) movl $0x40e00000, %eax movl %eax, -36(%ebp) fldl LC2 fstpl -48(%ebp) leave ret 

我在GCC(linux)上的64位处理器 (Intel Core 2 Duo)上编译了相同的代码

 legacyTypes: .LFB2: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 movq %rsp, %rbp .cfi_offset 6, -16 .cfi_def_cfa_register 6 movb $97, -1(%rbp) # char movb $97, -2(%rbp) # signed char movb $97, -3(%rbp) # unsigned char movl $1, -12(%rbp) # int movl $-2, -16(%rbp)# signed int movl $3, -20(%rbp) # unsigned int movw $4, -6(%rbp) # short int movq $5, -32(%rbp) # long int movq $6, -40(%rbp) # long long int movl $0x40e00000, %eax movl %eax, -24(%rbp) movabsq $4620693217682128896, %rax movq %rax, -48(%rbp) leave ret 

意见

  • char,signed char,unsigned char,int,unsigned int,signed int,short int,unsigned short int,signed short int all占用相同的no。 32位和64位处理器上的字节数。

  • 唯一的变化是在long intlong long int ,这些都在32位机器上占用32位,在64位机器上占用64位。

  • 还有指针,在32位CPU上采用32位,在64位CPU上采用64位。

问题:

  • 我不能说,这些书所说的是错的。 但我在这里遗漏了一些东西。 究竟什么“变量类型与机器有关?”
  • 如您所见,未签名和签名号码的说明没有区别。 那么为什么两者可以解决的数字范围不同呢?
  • 我正在阅读如何在不同的机器上保持C变量类型的固定大小? 我没有得到问题的目的或他们的答案。 什么保持固定大小? 它们都是一样的。 我不明白这些答案将如何确保相同的大小。

编辑:

是不是不可能在不同的机器上提供相同的尺寸? 我的意思是,如何在64位和32位机器上保持相同的指针大小?

依赖机器并不完全准确。 实际上,它是实现定义的 。 它可能取决于编译器,机器,编译器选项等。

例如,使用Visual C ++,即使在64位计算机上也是32位。

那里有更多的平台,其中一些是16位甚至8位! 在这些方面,你会发现所有上述类型的尺寸差异更大。

相同基本类型的有符号和无符号版本在任何平台上占用相同的字节数,但是它们的数字范围是不同的,因为对于带符号的数字,在有符号和无符号域之间共享相同范围的可能值。

例如,16位带符号的int可以具有从-32767(或许多平台上的-32768)到32767的值。相同大小的无符号int在0到65535的范围内。

在此之后,希望您更好地理解所提问题的重点。 基本上如果你编写一个程序,假设例如你的signed int变量将能够保持2 * 10 ^ 9(20亿)的值,那么你的程序是不可移植的,因为在某些平台(16位及以下)这个值会导致溢出,导致沉默,很难找到错误。 因此,例如在16位平台上,您需要#define您的整数很long ,以避免溢出。 这是一个简单的例子,它可能无法在所有平台上运行,但我希望它能为您提供一个基本的想法。

平台之间所有这些差异的原因是,在C标准化的时候,已经有许多C编译器被用于过多的不同平台,因此为了向后兼容,所有这些变种都必须被认为是有效的。

究竟什么“变量类型与机器有关?”

它完全意味着它所说的:大多数整体C类型的大小取决于机器(不是真正的机器 ,而是架构和编译器)。 当我在90年代早期做了很多C时, int大多是16位; 现在它大多是32位。 早于我的C职业,它可能是8位。 等等。

显然,你用于64位编译的C编译器的设计者决定int应保持32位。 不同C编译器的设计者可能会做出不同的选择。

如果你要重复测试,例如,摩托罗拉68000处理器,你会发现你会得到不同的结果(一个字是16位,一个长是32 – 通常是一个字是int)

真正的编译器通常不会利用标准允许的所有变化。 标准中的要求只给出了类型的最小范围 – 对于char为8位,对于short和int为16位,对于long为32位,(在C99中)为64位(对于long long)(该列表中的每个类型必须为具有至少与前述类型一样大的范围)。

但是,对于真正的编译器,向后兼容性几乎总是一个主要目标。 这意味着他们有很强的动力去改变,只要他们可以逃脱。 因此,在实践中,编译器之间的通用性要高于标准要求。

这是另一种实现 – 与你习惯的完全不同,但今天仍然存在于互联网上,即使它不再用于复古计算爱好者除外的通用计算 – 没有尺寸和你的一样:

 @type sizes.c #include  #include  int main() { printf("CHAR_BIT = %d\n", CHAR_BIT); printf("sizeof(char) = %d\n", sizeof(char)); printf("sizeof(short) = %d\n", sizeof(short)); printf("sizeof(int) = %d\n", sizeof(int)); printf("sizeof(long) = %d\n", sizeof(long)); printf("sizeof(float) = %d\n", sizeof(float)); printf("sizeof(double) = %d\n", sizeof(double)); return 0; } @run sizes.exe CHAR_BIT = 9 sizeof(char) = 1 sizeof(short) = 2 sizeof(int) = 4 sizeof(long) = 4 sizeof(float) = 4 sizeof(double) = 8