C运算符结果类型
在C11(n1570)中,有一些运算符的结果类型已明确说明。例如,&&的结果具有int类型。 但是我还没有找到其他操作符的结果类型,比如+。是否在标准中有规定 我试过这个程序:C运算符结果类型,c,casting,C,Casting,在C11(n1570)中,有一些运算符的结果类型已明确说明。例如,&&的结果具有int类型。 但是我还没有找到其他操作符的结果类型,比如+。是否在标准中有规定 我试过这个程序: unsigned char usc = 254; unsigned int usi = 4294967293; signed char sic = 126; long long unsigned llu = usc*2; printf("%llu\n",llu); llu = usi*2; printf("%llu\n"
unsigned char usc = 254;
unsigned int usi = 4294967293;
signed char sic = 126;
long long unsigned llu = usc*2;
printf("%llu\n",llu);
llu = usi*2;
printf("%llu\n",llu);
llu = usc+usc;
printf("%llu\n",llu);
llu = usi+usi;
printf("%llu\n",llu);
llu = usc+4294967294;
printf("%llu\n",llu);
llu = usc+2147483646;
printf("%llu\n",llu);
llu = sic+4294967294;
printf("%llu\n",llu);
llu = sic+2147483646;
printf("%llu\n",llu);
输出:
508
4294967290
508
4294967290
4294967548
18446744071562068220
4294967420
18446744071562068092
我猜这里提升了unsigned char,但是unsigned int没有;char+unsigned int的结果类型似乎是unsigned int,char+int的结果类型似乎是int
但我不太确定
这些铸件是标准的还是定义了实现的?在您的示例中没有“铸件”,只有转换。强制转换是一种语法构造,如引起转换的
(unsigned long)
。转换也会自行发生,就像在您的示例中一样
示例中发生的转换的名称是“常用算术转换”。C11标准第6.3.1.8条对其进行了描述,该条款太长,无法完整引用(当程序包含1+1.0
时,它还处理从整数类型到浮点类型的转换)。对于整数类型,规则如下所示:
如果两个操作数的类型相同,则不需要进一步转换
需要
否则,如果两个操作数都具有有符号整数类型或两者都具有
具有无符号整数类型,类型为较小的操作数
整数转换秩转换为具有
更高的等级
否则,如果具有无符号整数类型的操作数
等级大于或等于其他类型的等级
操作数,则带符号整数类型的操作数转换为
具有无符号整数类型的操作数的类型
否则,如果
带符号整数类型的操作数的可表示所有
具有无符号整数类型的操作数类型的值,然后
无符号整数类型的操作数转换为
带符号整数类型的操作数
否则,两个操作数均为空
已转换为与类型“”对应的无符号整数类型
带符号整数类型的操作数
结果的类型与为操作数确定的常用类型相同。
的前端,如果您正在使用Linux,它只需要一个“apt get install”就可以了。当您命令它打印它所构建的抽象语法树时,它会显式地将这些转换显示为强制转换。在您的示例中,转换是(删除不添加信息的printf()
调用):
这是一个通用的ILP32体系结构。实现定义的参数可能会影响转换,例如,对于大多数C99编译器,
40000
的类型可能是int
,对于其他编译器,long int
(它始终是列表中可以表示常量的第一种类型int
,long int
).标准明确规定了这些规则:
6.3.1.8常用算术转换
1许多期望算术类型的操作数的运算符会导致转换并产生结果
以类似的方式输入。目的是确定操作数的通用实数类型
结果呢。对于指定的操作数,将转换每个操作数,而不更改类型
域,指向其对应实类型为公共实类型的类型。除非
否则,公共实数类型也是
结果,其类型域是操作数的类型域(如果操作数相同),
否则会很复杂。这种模式称为通常的算术转换:
- 首先,如果其中一个操作数的对应实数类型为长双精度,则另一个操作数 操作数在不改变类型域的情况下被转换为相应实型为长双精度的类型
- 否则,如果任一操作数的对应实数类型为双精度,则另一个操作数 操作数在不更改域类型的情况下转换为 对应的实数类型是double
- 否则,如果其中一个操作数的对应实数类型为float,则另一个操作数 操作数在不更改域类型的情况下转换为 相应的实数类型是float.62)
- 否则,将对两个操作数执行整数提升。然后
以下规则应用于提升的操作数:
- 如果两个操作数的类型相同,则无需进一步转换
- 否则,如果两个操作数都具有有符号整数类型或都具有无符号整数类型 整数类型,则类型为较小整数转换秩的操作数为 已转换为具有更高秩的操作数类型
- 否则,如果具有无符号整数类型的操作数的秩大于或等于 等于另一个操作数类型的秩,然后为 有符号整数类型转换为无符号的操作数类型 整数类型
- 否则,如果带符号整数类型的操作数的类型可以表示 具有无符号整数类型的操作数类型的所有值,然后 无符号整数类型的操作数转换为 带符号整数类型的操作数
- 否则,两个操作数都将转换为无符号整数类型 对应于带符号整数类型的操作数的类型
您正确地推断了实现的结果。6.3.1.8为您提供了所有答案。我想说这两个:
llu=usc+2147483646代码>和llu=sic+2147483646代码>,是自int结果包装后定义的实现,然后分配给llu。@这第二行已经是实现定义的<
$ frama-c -print t.c
...
usc = (unsigned char)254;
usi = 4294967293;
sic = (signed char)126;
llu = (unsigned long long)((int)usc * 2);
llu = (unsigned long long)(usi * (unsigned int)2);
llu = (unsigned long long)((int)usc + (int)usc);
llu = (unsigned long long)(usi + usi);
llu = (unsigned long long)((unsigned int)usc + 4294967294);
llu = (unsigned long long)((int)usc + 2147483646);
llu = (unsigned long long)((unsigned int)sic + 4294967294);
llu = (unsigned long long)((int)sic + 2147483646);