我被告知C类型与机器有关。今天我想验证它。
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位和2位字节的字节数64位处理器。
唯一的变化是long int
& long long int
这两个版本在32位机器和32位机器上占用32位。 64位计算机上的64位。
还有指针,32位CPU和32位32位64位CPU上的64位。
问题:
修改
是不是不可能在不同的机器上提供相同的尺寸?我的意思是,如何在64位和16位上保持相同的指针大小。 32位机器?
答案 0 :(得分:8)
还有更多的平台,其中一些是16位甚至8位!在这些方面,你会发现所有上述类型的大小差别更大。
相同基本类型的有符号和无符号版本在任何平台上占用相同的字节数,但是它们的数字范围是不同的,因为对于带符号的数字,在有符号和无符号域之间共享相同范围的可能值。 / p>
E.g。 16位带符号的int可以具有-32767(或许多平台上的-32768)到32767的值。相同大小的无符号int的范围是0到65535.
在此之后,希望您更好地理解所提问题的重点。基本上,如果你写一个程序假设,例如你的signed int变量将能够保存2 * 10 ^ 9(20亿)的值,你的程序是不可移植的,因为在某些平台(16位及以下)这个值会导致溢出,导致沉默而难以发现错误。所以例如在16位平台上,您需要#define
您的整数long
以避免溢出。这是一个简单的例子,它可能无法在所有平台上运行,但我希望它能为您提供一个基本的想法。
平台之间所有这些差异的原因是,在C标准化的时候,已经有很多C编译器在很多不同的平台上使用,因此为了向后兼容,所有这些变种都必须被认为是有效的。 / p>
答案 1 :(得分:7)
依赖于机器并不十分准确。实际上,它是实现定义的。它可能取决于编译器,机器,编译器选项等。
例如,使用Visual C ++,即使在64位计算机上,long
也是32位。
答案 2 :(得分:4)
“变量类型是机器相关的意思是什么?”
这正是它所说的:大多数整数C类型的大小与机器相关(不是真正的机器,而是架构和编译器)。当我在90年代早期做了很多C时,int
大多是16位;现在它大多是32位。早于我的C职业,它可能是8位。等
显然,您用于64位编译的C编译器的设计者决定int
应保持32位。不同C编译器的设计者可能会做出不同的选择。
答案 3 :(得分:1)
如果你要重复测试,例如,摩托罗拉68000处理器,你会发现你会得到不同的结果(一个字是16位,一个长是32 - 通常是一个字是int)
答案 4 :(得分:1)
真正的编译器通常不会利用标准允许的所有变体。标准中的要求仅为类型提供最小范围 - 对于char为8位,对于short和int为16位,对于long为32位,(在C99中)为64位(对于long long)(并且该列表中的每个类型必须至少具有与前一类型一样大的范围。
对于真正的编译器,向后兼容性几乎总是一个主要目标。这意味着他们有很强的动力去改变,只要他们可以逃脱。因此,在实践中,编译器之间的通用性要高于标准要求。
答案 5 :(得分:1)
这是另一种实现 - 与你习惯的完全不同,但今天仍然存在于互联网上,即使它不再用于通用计算,但复古计算爱好者除外 - 无大小与你的相同:
@type sizes.c
#include <stdio.h>
#include <limits.h>
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