如何在 C++ 中编写简短的文字?
Posted
技术标签:
【中文标题】如何在 C++ 中编写简短的文字?【英文标题】:How do I write a short literal in C++? 【发布时间】:2008-10-16 12:57:34 【问题描述】:非常基本的问题:如何在 C++ 中编写 short
文字?
我知道以下几点:
2
是 int
2U
是 unsigned int
2L
是 long
2LL
是 long long
2.0f
是 float
2.0
是 double
'\2'
是 char
。
但是我将如何编写 short
文字?我尝试了2S
,但这给出了编译器警告。
【问题讨论】:
我猜不支持短文字仅仅是因为在评估期间任何小于 int 的东西都会被“提升”为 int 。 int 具有最自然的大小。这在 C++ 中称为整数提升。 【参考方案1】:((short)2)
是的,严格来说,它不是一个简短的文字,更像是一个强制转换的整数,但行为是相同的,我认为没有直接的方法。
这就是我一直在做的,因为我找不到任何关于它的东西。我猜编译器会足够聪明地编译它,就好像它是一个短文字(即它实际上不会分配一个 int 然后每次都强制转换它)。
以下内容说明了您应该为此担心多少:
a = 2L;
b = 2.0;
c = (short)2;
d = '\2';
编译->反汇编->
movl $2, _a
movl $2, _b
movl $2, _c
movl $2, _d
【讨论】:
这就是我一直在做的事情,因为我找不到任何关于它的信息。我猜编译器会足够聪明地编译它,就好像它是一个短文字(即它实际上不会分配一个 int 然后每次都强制转换它)。 “演员”实际上并没有做任何事情。当我们谈论 C 或 C++ 时,没有“强制转换”汇编指令(不过.NET MSIL 是另一回事)。在金属上,都是二进制数字 上面的a,b,c,d有哪些类型? @Ates Goral:所有整数。更改为 short 或 char 可能会将指令更改为 movw 或 movb 全面。 这不是简短的文字。当您使用该转换并使用 GCC 和选项 -Wconversion 进行编译时,您仍然可以获得语句short foo = 1; foo += (short)2;
的编译器诊断。但是由于整数提升,这是无法避免的。【参考方案2】:
C++11 给你非常接近你想要的东西。 (搜索“用户定义的文字”以了解更多信息。)
#include <cstdint>
inline std::uint16_t operator "" _u(unsigned long long value)
return static_cast<std::uint16_t>(value);
void func(std::uint32_t value); // 1
void func(std::uint16_t value); // 2
func(0x1234U); // calls 1
func(0x1234_u); // calls 2
// also
inline std::int16_t operator "" _s(unsigned long long value)
return static_cast<std::int16_t>(value);
【讨论】:
short
物理上不能是 std::uint
anything,因为它是签名类型。并且它不需要是 16 位或与 std::int16_t
... 相同的类型,如果平台无法提供确切的宽度,则它本身甚至不需要在给定的实现中存在类型。这个答案的核心思想很好,但它被莫名其妙的切线贬低为OP没有询问的不相关类型。
注意,在 VS2015 之前,Visual Studio 不支持用户定义的文字:msdn.microsoft.com/en-us/library/hh567368(v=vs.140).aspx
我不知道该喜欢还是讨厌它,但这是我正在研究的 C++ 中的实际 Strong 整数类型系统的最后一部分,它是太棒了。
呼应@underscore_d,我会投赞成票,但在 OP 要求编辑short
之后。
@lars,它确实适用于签名类型。 unsigned long long int
包含一个已知适合short 的值将转换得很好。可以并且应该添加各种编译时和运行时检查以确保该值在范围内,此代码绝对有效。请注意,C++ 中没有带符号的文字;表达式 -42
实际上是文字 42
前面有否定运算符。因此,在 Ken 的示例中,-42_s
将产生等效于 -static_cast<int16_t>(42ULL)
的值,即具有值 -42
的 int16_t
。【参考方案3】:
即使是 C99 标准的编写者也被这一点所吸引。这是来自 Danny Smith 的公共域 stdint.h
实现的 sn-p:
/* 7.18.4.1 Macros for minimum-width integer constants
Accoding to Douglas Gwyn <gwyn@arl.mil>:
"This spec was changed in ISO/IEC 9899:1999 TC1; in ISO/IEC
9899:1999 as initially published, the expansion was required
to be an integer constant of precisely matching type, which
is impossible to accomplish for the shorter types on most
platforms, because C99 provides no standard way to designate
an integer constant with width less than that of type int.
TC1 changed this to require just an integer constant
*expression* with *promoted* type."
*/
【讨论】:
【参考方案4】:如果您使用 Microsoft Visual C++,则每种整数类型都有可用的文字后缀:
auto var1 = 10i8; // char
auto var2 = 10ui8; // unsigned char
auto var3 = 10i16; // short
auto var4 = 10ui16; // unsigned short
auto var5 = 10i32; // int
auto var6 = 10ui32; // unsigned int
auto var7 = 10i64; // long long
auto var8 = 10ui64; // unsigned long long
请注意,这些是非标准扩展并且不可移植。事实上,我什至在 MSDN 上都找不到关于这些后缀的任何信息。
【讨论】:
当您跟踪其中一个后缀时,您会看到例如""ui8
定义为'\000'
,本质上是'\0'
。【参考方案5】:
您还可以使用伪构造函数语法。
short(2)
我发现它比强制转换更具可读性。
【讨论】:
它被称为“函数式转换表达式”。我也非常喜欢它,尤其是在使用 Windows API 编程时。【参考方案6】:据我所知,你没有,没有这样的后缀。不过,如果整数文字太大而无法放入您尝试存储它的任何变量,大多数编译器都会发出警告。
【讨论】:
【参考方案7】:一种可能性是为此目的使用 C++11“列表初始化”,例如:
short42;
此解决方案的优点(与当前接受的答案中的强制转换相比)是它不允许缩小转换:
auto number1 = short(100000); // Oops: Stores -31072, you may get a warning
auto number2 = short100000; // Compiler error. Value too large for type short
请参阅 https://en.cppreference.com/w/cpp/language/list_initialization#Narrowing_conversions 了解使用 list-init 进行的禁止缩小转换
【讨论】:
我已经有一段时间没有做 C/C++ 了。你能像short mynum = short42;
一样使用它吗?
@Kip 可以,但我通常使用short variable123
来声明和初始化一个变量。 short123
的形式很有用,例如当您只需要一个短(或任何类型)数字但没有变量来分配它时。这例如在单元测试断言中经常发生在我身上,您不仅需要提供预期值,还需要提供预期类型。以上是关于如何在 C++ 中编写简短的文字?的主要内容,如果未能解决你的问题,请参考以下文章
c++ 编译器如何从 utf8 源文件生成 unicode 字符串文字
如何在 VIsual C++ 2010 中实现 C++ 原始字符串文字?