【发布时间】:2014-05-25 18:11:06
【问题描述】:
我不知道如何称呼这些标志,但我指的是:
#define TEST_DEF 50000U //<- the "U" here
当您不熟悉用于描述您的问题的术语时,Google 搜索是徒劳的。
我要做的是使用这些常量定义并确保该值仅具有一定的长度,即 8 位或 16 位。
我该怎么做?它被称为什么?
【问题讨论】:
我不知道如何称呼这些标志,但我指的是:
#define TEST_DEF 50000U //<- the "U" here
当您不熟悉用于描述您的问题的术语时,Google 搜索是徒劳的。
我要做的是使用这些常量定义并确保该值仅具有一定的长度,即 8 位或 16 位。
我该怎么做?它被称为什么?
【问题讨论】:
对于整数,定义这些后缀的标准部分(ISO/IEC 9899:2011 — 也称为 C2011 或 C11)是:
§6.4.4.1 整数常量
定义整数后缀的地方:
整数后缀:
无符号后缀长后缀opt
unsigned-suffix long-long-suffix
长后缀无符号后缀opt
long-long-suffix unsigned-suffixopt无符号后缀:
之一u U长后缀:
之一l Llong-long-suffix:
之一ll LL
浮点数对应的后缀是f、F、l和L(对于float和long double)。
请注意,使用l 是不恰当的,因为它很容易与1 混淆,因此限定词通常用大写字母书写。
如果您想要创建具有给定大小的整数文字,那么执行此操作的工具由 <stdint.h> 标准化(在 C99 中添加)。
标头(有条件地)定义固定大小的类型,例如int8_t 和uint16_t。它还(无条件地)提供最小大小的类型,例如int_least8_t 和uint_least16_t。如果它不能提供精确的类型(可能是因为字长是 36 位,所以处理了 9、18 和 36 的大小),它仍然可以提供最少的类型。
它还提供了诸如INT8_C 之类的宏来确保参数是int_least8_t 值。
因此,您可以使用:
#include <stdint.h>
#define TEST_DEF UINT16_C(50000)
并且您可以保证该值至少是 16 位无符号整数,并且格式/限定正确。
§7.20.4 用于整数常量的宏
¶1 以下类似函数的宏扩展为适合初始化的整数常量 具有与
<stdint.h>中定义的类型相对应的整数类型的对象。每个 宏名称对应于 7.20.1.2 或 7.20.1.5 中的类似类型名称。¶2 这些宏的任何实例中的参数都应是无后缀的整数常量(如 在 6.4.4.1 中定义),其值不超过相应类型的限制。
¶3 这些宏之一的每次调用都应扩展为整数常量表达式 适用于#if 预处理指令。表达式的类型应具有 与根据以下转换的相应类型的表达式相同的类型 整数促销。表达式的值应该是参数的值。
7.20.4.1 最小宽度整数常量的宏
¶1 宏
INTN_C(value)应扩展为整数常量表达式 对应于类型int_leastN_t。宏UINTN_C(value)应展开 对应于类型uint_leastN_t的整数常量表达式。为了 例如,如果uint_least64_t是unsigned long long int类型的名称, 那么UINT64_C(0x123)可能会扩展为整数常量0x123ULL。
【讨论】:
C 中有五个整数文字后缀:u、l、ul、ll 和 ull。与 C 中的几乎所有其他内容不同,它们不区分大小写;另外,ul 和 ull 可以分别写为 lu 和 llu(但是,lul 是不可接受的)。
它们控制常量的类型。它们大约像这样工作:
literal │ type
────────┼───────────────────────
500 │ int
500u │ unsigned int
500l │ long int
500ul │ unsigned long int
500ll │ long long int
500ull │ unsigned long long int
这只是一个近似值,因为如果常数对于指定的类型来说太大了,它会被“提升”为更大的类型。这个规则非常复杂,我不打算描述它们。 “提升”十六进制和八进制文字的规则与“提升”十进制文字的规则略有不同,在 C99 和 C90 中也略有不同,在 C++ 中也有所不同。
由于提升效果,无法使用这些后缀将常量限制为任何大小。如果您在int 和long 都是32 位宽的系统上编写281474976710656,即使您没有说要这样做,常量也会被赋予long long 类型。此外,没有后缀可以强制常量具有short 或char 类型。您可以使用来自<stdint.h> 的[U]INT{8,16,32,64,MAX}_C 宏来表明您的意图,但这些宏也没有施加任何上限,并且在我现在可以方便地使用的所有系统(OSX、Linux)上, *INT8_C 和 *INT16_C 实际上会产生 (unsigned) int 类型的值。
您的编译器可能在您编写 ((uint8_t) 512) 或类似内容时发出警告(其中 512 是超出类型范围的编译时常量值。在 C11 中,您可以使用static_assert(来自<assert.h>)来强制解决这个问题,但写起来可能有点乏味。
【讨论】:
这是一个无符号文字(U 是后缀)。见:http://en.cppreference.com/w/cpp/language/integer_literal
【讨论】: