如何在编译时自动区分短和长?

问题描述 投票:22回答:6

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

auto foo = 12;

foo的类型可以合理地是int甚至unsigned char。但是假设在我的程序中稍后我会做一些数学并给foo赋值40亿。在那一点上,我希望foo成为unsigned int类型或者long

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

c++ c++11 auto
6个回答
50
投票

编译器使用存在的信息,在您的情况下是整数文字12。所以它推断出fooint类型。它没有任何预期。您可以使用适当的integer literal后缀:

auto foo = 12ul;

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

有关该主题的更多信息,请查看auto specifierauto type deduction参考。


23
投票

“foo的类型可以合理地为int或甚至unsigned char”

不,它不能。 C ++中的每个表达式都有一个类型,并且在语言中明确定义。在您的情况下,表达式是整数文字,因此类型对应于文字。具体是什么类型,由rules定义:

文字的类型

整数文字的类型是值可以适合的第一种类型,从类型列表中取决于使用哪个数字基数和哪个整数后缀。

无后缀 - int,long int,long long int(自C ++ 11起)

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

这不可以。声明变量时确定类型,以后不能更改。


10
投票

foo的类型可以合理地为int或甚至unsigned char

它可能是很多东西,但它实际上只是一件事。

整数文字12的类型为int

期。

但是假设后来在我的程序中,我做了一些数学运算并给foo赋值40亿。那时,我希望foo有类型unsigned int或者long。编译器如何预测将在程序中稍后分配的值?

他们不能,他们不能。 foo的类型不会改变。 foo没有类型auto(没有这样的东西);它有类型int。你今后的计划就好像你写了int foo = 12;。演绎/自动化在那里结束。


5
投票

那时,我希望foo有类型unsigned int或者long

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

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

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


4
投票

我的建议是,这不是一个使用auto的好地方。您知道哪些因素决定了您需要的类型,并且无法从直接上下文中推断出它们。 (但是,如果您可以将变量编写为单个静态赋值,则不会发生这种情况。)

如果您知道变量需要能够保存至少40亿的值,请将其声明为unsigned longlong long int。或者,如果您真的想要针对这些类型的宽度(例如long为32位宽以支持遗留代码,但本机字大小为64位的平台)进行防御性编码,请将其声明为uint_fast32_tint_fast64_t。或者如果你想要最小的,而不是最快的uint_least32_t。 (有时,最快的代码是在缓存中保留最多值的代码!)

如果你真正想要的是最快的签名或无符号类型,可以保持40亿的价值,说出你的意思!


1
投票

就个人而言,我不会对这些直接常量使用auto,但是值来自另一个方法调用,或者从另一个变量赋值。

如果你想要一种方法来定义一个变量以匹配另一个变量的类型,那么你可以与它进行互操作,但是你想要分配一个常量值,然后使用decltype来确保它的大小是兼容的:

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

在任何情况下,类型由文字常量指定,未修饰的12将定义int。

但是,您可以使用U来装饰常量,使其无符号,或者使L变长,或者使LL变长,以使其超长。不幸的是,没有相当于强迫它短或char!

© www.soinside.com 2019 - 2024. All rights reserved.