您可能想在 C++ 中使用以下内容来理解这一点:
#include<iostream>
#include<cxxabi.h>
using namespace std;
using namespace abi;
int main () {
int status;
cout << __cxa_demangle(typeid(2000*2000*2000*2000).name(),0,0,&status);
}
如您所见,类型为int。
在 C 中,您可以使用 (courtesy of):
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#define typename(x) _Generic((x), /* Get the name of a type */ \
\
_Bool: "_Bool", unsigned char: "unsigned char", \
char: "char", signed char: "signed char", \
short int: "short int", unsigned short int: "unsigned short int", \
int: "int", unsigned int: "unsigned int", \
long int: "long int", unsigned long int: "unsigned long int", \
long long int: "long long int", unsigned long long int: "unsigned long long int", \
float: "float", double: "double", \
long double: "long double", char *: "pointer to char", \
void *: "pointer to void", int *: "pointer to int", \
char(*)[]: "pointer to char array", default: "other")
unsigned int a = 3;
int main() {
printf("%s", typename(a-10));
return 0;
}
这里表达式的类型是unsigned int,因为类型不匹配隐式地将类型升级为unsigned int和int之间的最大类型,即unsigned int。 unsigned int 将下溢到一个大的正数,当分配给或解释为int 时,这将是预期的负数。计算结果将始终为unsigned int,无论所涉及的值如何。
C
不带后缀的整数字面量的最小默认类型是int,但只有字面量超过这个值,它的类型才会变成unsigned int;如果大于它,则给出long int 的类型,因此2000s 都是ints。然而,在文字上执行的 表达式 的类型,使用一元或二元运算符,使用隐式类型层次结构来决定类型,而不是结果的值(不像文字本身,它使用决定类型的文字),这是因为 C 使用类型强制而不是类型合成。为了解决这个问题,您必须在 2000 年代使用长后缀 ul 来明确指定文字的类型。
同样,十进制字面量的默认类型是double,但可以使用f 后缀来更改。前缀不会改变十进制或整数文字的类型。
字符串字面量的类型是char [],虽然它实际上是const char [],并且只是该字符串字面量在.rodata中的实际表示中的第一个字符的地址,地址可以是像使用一元 & 符号&"string" 的任何数组一样,它与"string" 具有相同的值(地址),只是类型不同(char (*)[7] 与char[7];"string" 即char[] 不只是(在编译器级别)指向数组的指针,它是数组,而一元&符号仅提取指向数组的指针)。 u 前缀将其更改为char16_t 的数组,即unsigned short int; U 前缀将其更改为char32_t 的数组,即unsigned int;并且L 前缀将其更改为wchar_t 的数组,即int。 u8 是 char 并且无前缀字符串使用特定于实现的编码,这通常与 u8 相同,即 UTF-8,其中 ASCII 是一个子集。 raw (R) prefix 仅适用于字符串文字(并且仅适用于 GNU C(std=gnu99 以上))可以作为前缀,即 uR 或 u8R,但这不会影响类型。
字符文字的类型是int,除非前缀为u(u'a' 是unsigned short int)或U(U'a' 是unsigned int)。 u8 和 L 在用于字符文字时都是 int。字符串或字符文字中的转义序列不会影响编码和类型,它只是将要编码的字符实际呈现给编译器的一种方式。
复数字面量10i+1 或10j+1 的类型是complex int,其中实部和虚部都可以有一个后缀,例如10Li+1,在这种情况下,它使虚部变长,而整体类型为complex long int,同时升级了实部和虚部的类型,所以不管你把后缀放在哪里,或者把它放在两者上都没有关系。不匹配将始终使用两个后缀中最大的一个作为整体类型。
如果你正确使用它并意识到它截断/扩展的语义差异,使用显式转换而不是文字后缀总是会导致正确的行为(符号扩展为signed;零扩展为unsigned –这是基于被强制转换的文字或表达式的类型,而不是被强制转换为的类型,因此signed int 被符号扩展为unsigned long int) 该类型表达式的文字,而不是固有的文字有那种类型。
C++
同样,最小的默认类型是int,表示最小的文字基数。字面量基础即字面量的实际值,后缀根据下表影响最终的字面量类型,在每个后缀的每个框中,最终类型的顺序根据实际的大小从小到大排列字面基础。对于每个后缀,字面量的最终类型只能等于或大于后缀类型,并且取决于字面量基数的大小。 C 表现出相同的行为。当大于long long int 时,根据编译器,使用__int128。我认为您也可以创建自己的文字后缀运算符 i128 并返回该类型的值。
十进制字面量的默认类型与C相同。
字符串文字的类型是char []。 &"string" 的类型是 const char (*) [7],+"string" 的类型是 const char *(在 C 中你只能使用 "string"+0 衰减)。 C++ 的不同之处在于后两种形式获取 const 但在 C 中它们没有。字符串前缀的行为与 C 中的相同
字符和复杂文字的行为与 C 相同。