我不明白为什么sizeof运营商产生以下结果:
sizeof( 2500000000 ) // => 8 (8 bytes).
Run Code Online (Sandbox Code Playgroud)
...它返回8,当我执行以下操作时:
sizeof( 1250000000 * 2 ) // => 4 (4 bytes).
Run Code Online (Sandbox Code Playgroud)
...它返回4而不是8(这是我的预期).有人可以澄清如何sizeof确定表达式(或数据类型)的大小以及为什么在我的特定情况下会发生这种情况?
我最好的猜测是sizeof运算符是编译时运算符.
赏金问题:是否有运行时运算符可以评估这些表达式并产生我的预期输出(没有强制转换)?
Luc*_*ore 123
2500000000不适合int,所以编译器正确地将其解释为long(或long long,或适合的类型).1250000000是的,等等2.sizeof 不计算参数to ,因此编译器不可能知道乘法不适合a int,因此返回a的大小int.
此外,即使评估了参数,您也可能会遇到溢出(和未定义的行为),但可能仍会导致4.
这里:
#include <iostream>
int main()
{
long long x = 1250000000 * 2;
std::cout << x;
}
Run Code Online (Sandbox Code Playgroud)
你能猜出输出吗?如果你认为这样2500000000,你就错了.表达式的类型1250000000 * 2是int,因为操作数是int和,int并且如果不适合,乘法不会自动提升为更大的数据类型.
所以在这里,gcc说它是-1794967296,但它是未定义的行为,因此可以是任何数字.这个数字确实适合int.
另外,如果你将其中一个操作数强制转换为期望的类型(就像你在寻找非整数结果时分割整数一样),你会看到这个工作:
#include <iostream>
int main()
{
long long x = (long long)1250000000 * 2;
std::cout << x;
}
Run Code Online (Sandbox Code Playgroud)
产生正确的2500000000.
[编辑:我最初没有注意到,这是作为C和C++发布的.我只回答关于C.]
回答你的后续问题,"无论如何确定在运行时分配给表达式或变量的内存量?":好吧,不完全是.问题是这不是一个非常好的问题.
C语言中的"表达式"(与某些特定实现相反)实际上并不使用任何内存.(具体实现需要一些代码和/或数据存储器来保存计算,具体取决于有多少结果适合CPU寄存器等等.)如果表达式结果没有隐藏在变量中,它就会消失(并且编译器可以经常省略运行时代码来计算从未保存的结果).该语言没有给你一种方式来询问它不存在的东西,即表达式的存储空间.
另一方面,变量确实占用存储空间(存储器).变量的声明告诉编译器要留出多少存储空间.但是,除了C99的可变长度数组之外,所需的存储仅在编译时确定,而不是在运行时确定.这就是为什么sizeof x通常是一个常量表达式:编译器可以(实际上必须)确定sizeof x编译时的值.
C99的VLA是该规则的特殊例外:
void f(int n) {
char buf[n];
...
}
Run Code Online (Sandbox Code Playgroud)
所需的存储buf不是(通常)编译器在编译时可以找到的东西,因此sizeof buf不是编译时常量.在这种情况下,buf实际上是在运行时分配,然后仅确定其大小.所以sizeof buf 是一个运行时计算的表达.
但是,在大多数情况下,所有内容都在编译时预先确定大小,如果表达式在运行时溢出,则行为是未定义的,实现定义的,或者根据类型定义良好.有符号整数溢出,如25亿乘以2,当INT_MAX仅略高于27亿时,会导致"未定义的行为".无符号整数执行模运算,因此允许您在GF(2 k)中进行计算.
如果你想确保一些计算不能溢出,那么你必须在运行时自己计算.这是使多精度库(如gmp)难以用C编写的一个重要部分 - 它通常更容易,更快,在汇编中编写大部分内容并利用CPU的已知属性(如溢出标志,或双宽结果寄存器对).
Luchian已经回答了.只是为了完成它..
C11标准状态(C++标准具有类似的行),指定类型的没有后缀的整数文字的类型被确定如下:
从6.4.4常数(C11草案):
语义
4十进制常数的值以10为基数计算; 八进制常数,基数为8; 十六进制常量的基数16.词汇的第一个数字是最重要的.
5整数常量的类型是相应列表中可以表示其值的第一个.
表格如下:
十进制常数
int
int long int
long long int
Run Code Online (Sandbox Code Playgroud)
八进制或十六进制常数
int
unsigned int
long int
unsigned long int
long long int
unsigned long long int
Run Code Online (Sandbox Code Playgroud)
对于八进制和十六进制常量,甚至可以使用无符号类型.因此,根据您的平台,上面列表中的任何一个(int或long int或long long int)首先匹配(按顺序)将是整数文字的类型.
| 归档时间: |
|
| 查看次数: |
3597 次 |
| 最近记录: |