自动在编译时如何将缩写与长期区分

How can auto distinguish short from long at compile time?

本文关键字:缩写 期区 编译      更新时间:2023-10-16

我很高兴能在我的C 程序中使用auto变量。我知道使用auto声明的变量使用模板规则推断变量类型,但是我对数字类型的工作方式感到困惑。假设我有:

auto foo = 12;

foo的类型可以合理地为int甚至unsigned char。但是,假设在我的程序后面,我进行了一些数学,并为FOO分配了40亿个价值。那时,我希望foo成为unsigned int型或long

编译器如何预期在程序稍后将分配的值?

编译器与存在的信息一起使用,在您的情况下是整数文字12。因此,它将foo推论为int类型。它没有任何预期。您可以使用适当的整数字面后缀:

auto foo = 12ul;

迫使foo推导为unsigned long。您不能将变量定义为类型int,然后下线期望编译器以某种方式将其更改为另一种类型,仅仅是因为您分配了一个不适合先前使用类型的不同值。如果您这样做了,它将仅导致整数溢出,这是不确定的行为。

有关该主题的更多信息,请查看自动说明符和自动类型扣除参考。

; foo的类型可以合理地是int,甚至是未签名的char&quot&quot&quot

不,它不能。C 中的每个表达式都有一种类型,并且在语言中明确定义了。在您的情况下,表达式是整数字面的,因此类型与文字相对应。它是什么类型的,是由规则定义的:

字面的类型

整数字面的类型是该值可以拟合的第一种类型,从依赖于哪个数字碱和使用了哪个整数 - 苏联的类型列表中。

无后缀 - int,长int,长int(自C 11(

;编译器如何预期将在以后分配的值程序?&quot

不能。当您声明变量时确定类型,并且以后无法更改。

foo的类型可以合理地是int甚至未签名的char

可以是很多事情,但实际上只有一件事。

整数文字12具有类型int

期。

,但是假设稍后在我的程序中,我进行了一些数学,并为FOO分配了40亿。那时,我希望FOO具有UNSIGNED INT或更长时间的类型。编译器如何预测程序后面将分配的值?

他们做不到,而他们却没有。foo的类型不会改变。foo没有类型的auto(没有这样的东西(;它具有类型int。从此以后,您的程序就像您写了int foo = 12;一样。扣除/自动化结束。

那时,我希望foo具有unsigned intlong

这不是语言工作的方式。变量不能在运行时更改其类型。如果将变量定义为auto foo = 12;,则意味着与int foo = 12;完全相同的,无论未来的任何任务如何,因为12的类型是int

编译器如何预测程序后来将分配的值?

他们不必。稍后分配的值将转换为变量的类型。如果该类型的值不超出该类型的范围,则确切的规则取决于您要处理的类型。

我的建议不是使用auto的好地方。您知道哪些因素决定了您需要的类型,并且不能从直接上下文中推导。(但是,如果您可以将变量写为单个静态分配,那将永远不会发生。(

如果您知道该变量需要能够保持至少40亿个值,请将其声明为unsigned longlong long int。或者,如果您真的想防御不幸的选择这些类型的宽度(例如long的平台为32位宽32位以支持旧版代码,但本机字样是64位(,请将其声明为uint_fast32_tint_fast64_t。或者,如果您想要最小的,而不是最快的uint_least32_t。(有时,最快的代码是使缓存中保持最多值的代码!(

如果您真正想要的是最快的签名或未签名类型,可以容纳40亿个,请说出您的意思!

就这些即时常数而言,我不会使用auto,而是该值来自另一个方法调用或从另一个变量分配。

如果您确实想要一种定义变量以匹配另一个变量的类型的方法,以便您可以与之互操作,但是您想分配一个常数值,然后使用sectType确保其大小兼容:

decltype(otherVar) myVar = 1234;
myVar += otherVar;  // will work just as well as otherVar += myVar

在任何情况下,类型是由字面常数指定的,未装饰的12将定义一个int。

但是,您可以用u装饰常数,以使其无签名,或者l以使其长,甚至可以使其变得超长。不幸的是!

像所有其他答案一样,没有等效的迫使它短或字符。

但是还有其他一些方法可以预先指定所需类型。

auto foo = long(12);
std::cout << typeid(foo).name() << std::endl;
auto anotherFoo = long long (12);
//Some compilers may not allow multiple words like "long long"
//In that case you can use using keyword.
using llong = long long;
auto someOtherFoo = llong (12);