[英]Question in number of bits in C programming
如果我做
int a = 3 ,则 3 将用 32 位二进制表示。
如果我做
char a = 3 ,则 3 将用 8 位二进制表示。
我的问题是在使用值进行初始化之前, 3代表多少位?
(换句话说,“3”在等号右边有多少位)
int
具有 32 位是很常见的,但不能保证。 它也可以是 16 或 64。 或更高。
单个3
是int
类型的 integer 文字。
您可以使用sizeof
运算符检查它。 它会给你以字节为单位的参数大小。 只需尝试获取int
、 a
和3
的大小。
#include <stdio.h>
int main()
{
int a = 3;
printf("%ld\n", sizeof(a)); // gives 4 bytes (32 bit) on my PC
printf("%ld\n", sizeof(int)); // gives 4 bytes (32 bit) on my PC
printf("%ld\n", sizeof(3)); // gives 4 bytes (32 bit) on my PC
return 0;
}
此外, 3
的类型为int
。 所以它的大小等于int
的大小。
int
类型的 object 的大小是实现定义的 该标准仅要求INT_MAX
不得小于+32767
,即2 ^ 15 - 1
如果在您的系统中, int
类型的 object 的大小等于 4,那么像3
这样的 integer 常量将占用一个等于4
个字节的 memory 块。
请注意,例如字符 integer 常量也具有int
类型。
所以在这两个声明中
char a = 3;
和
char a = '\3';
如果sizeof( int )
等于4
,则具有int
类型的常量3
和'\3'
占用4
个字节。
3
被称为integer 常量,它的类型很像任何命名变量。 如果键入的数字可以放入int
int
否则,如果它不适合,编译器会尝试将它放入一个long
中,然后是long long
。
有各种相当复杂的规则来说明如何做到这一点,我不会在这里提及所有肮脏的细节——对此感兴趣的人可以查看 C 标准 6.4.4.1 中的表格。 对于普通程序员来说,知道我们还可以通过添加U
后缀来强制 integer 常量无符号或通过添加L
后缀强制它变long
可能就足够了。 即3U
或3L
或组合3UL
。 (小写的u
和l
也可以。)
在现实世界的计算机上, int
总是 2 或 4 字节大。 long
是 4 或 8 字节大。 来自具有 4 字节int
和 8 字节long
的 64 位 Linux 计算机的示例:
#include <stdio.h>
int main (void)
{
printf("%zu\n", sizeof(int)); // 4
printf("%zu\n", sizeof(3)); // 4
printf("%zu\n", sizeof(3L)); // 8
printf("%zu\n", sizeof(2147483647)); // 4, fits int
printf("%zu\n", sizeof(2147483648)); // 8, doesnt fit
}
问题“3 代表多少位?” 实际上很棘手。 如果我们能找到3,那么我们就可以回答它。 所以问题是: 3 在哪里?
真正发生的是:
int a = 3;
是相同的:
int a;
a = 3;
编译器确保变量a
将有 4 个字节的空间(它在编译时执行此操作),然后它还会在程序中放置一条指令,当您运行程序时将数字 3 存储在该空间中。
我们可以使用这个有用的在线工具来编译程序并查看编译器实际输出的汇编/机器代码: https://godbolt.org/z/a9Pohn
在这种情况下,我进入了程序:
int main() {
int a;
a = 3;
}
并用“x86-64 gcc 10.2”编译它,没有优化。 这是编译后的代码(汇编代码和机器代码):
main:
55 push rbp
48 89 e5 mov rbp,rsp
c7 45 fc 03 00 00 00 mov DWORD PTR [rbp-0x4],0x3
b8 00 00 00 00 mov eax,0x0
5d pop rbp
c3 ret
如果我们可以阅读汇编,我们可以看到编译器选择插入到程序中来初始化变量a
的指令是mov DWORD PTR [rbp-0x4],0x3
。 在机器代码中,它写成c7 45 fc 03 00 00 00
。 指令是数字 3 的来源。
该指令长 7 个字节。 c7 45
告诉 CPU 这是什么类型的指令(“在堆栈帧中的特定 position 中放入特定数字”)。 fc
是堆栈帧中的 position。 03 00 00 00
是它放在那里的特定数字(以小端格式)。 这是源代码中的数字 3。 所以在这种情况下,它占用了 4 个字节。
请注意,它并不总是相同的。 如果我们为 ARM CPU 而不是 x86-64 编译,那么这些是相关指令
mov r3, #3
str r3, [fp, #-8]
不幸的是,godbolt 不会向我们显示机器代码,但我们可以在 ARM 手册中查找 MOV # 指令,该指令告诉我们该指令长 4 个字节,而被移动的数字仅占用其中 2 个字节。 如果您使用的数字不适合 2 个字节,则其他位自动为零。 显然它使用了不同的指令。
通常我们不会谈论指令的大小,因为它们的变化比数据大小要大得多。 int a;
总是保留 4 个字节(如果您的系统的int
是 4 个字节),但是将特定位放入该空间的指令可以具有不同的大小。
即使在 x86-64 上,数字也可以占用不同数量的空间。 如果我确实return 0;
,编译器将其转换为xor eax, eax
( 31 c0
)。 该指令中根本没有数字0
! ( 31 c0
是所有类型的指令,没有数据)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.