使用gcc使用常量及其相关修饰符

Using constants and their associated modifiers using gcc

本文关键字:gcc 常量 使用      更新时间:2023-10-16

我不知道该怎么称呼这些标志,但我指的是:

#define TEST_DEF 50000U //<- the "U" here

当你不熟悉用来描述你的问题的术语时,谷歌搜索是徒劳的。

我要做的是使用这些常量定义,并确保值只有一定的长度,即8或16位。

我怎么做,它被称为什么?

对于整数,标准(ISO/IEC 9899:2011 -又名C2011或C11)定义这些后缀的部分为:

§6.4.4.1整型常量

其中定义了整数后缀:

integer-suffix :
,,, unsigned-suffix long-suffix <子>选择
,,, unsigned-suffix long-long-suffix
,,, long-suffix unsigned-suffix <子>选择
,,, long-long-suffix unsigned-suffix <子>选择

unsigned-suffix:
,,,,u U

long-suffix:,,,,l L

long-long-suffix:
,,,,ll LL

对应的浮点数后缀为fFlL (floatlong double)。

请注意,使用l是不合理的,因为它太容易与1混淆,所以限定符通常用大写字母书写。

如果您想要创建给定大小的整数字面值,那么<stdint.h>(在C99中添加)将实现此功能的标准化。

头(有条件地)定义了固定大小的类型,如int8_tuint16_t。它还(无条件地)提供最小大小的类型,如int_least8_tuint_least16_t。如果它不能提供确切的类型(可能因为字长是36位,所以可以处理9、18和36的大小),它仍然可以提供最少的类型。

它还提供了INT8_C这样的宏来确保参数是int_least8_t的值。

因此,您可以使用:

#include <stdint.h>
#define TEST_DEF UINT16_C(50000)

,您可以保证该值至少为16位无符号整数,并正确格式化/限定。

§7.20.4整型常量的宏

下面的类函数宏展开为适合初始化的整型常量具有与<stdint.h>中定义的类型对应的整数类型的对象。每一个宏名对应于7.20.1.2或7.20.1.5中类似的类型名。 这些宏的任何实例中的实参都必须是一个无后缀的整型常量(如定义于6.4.4.1),其值不超过对应类型的限制。 这些宏的每次调用都应该展开为一个整型常量表达式适合在#if预处理指令中使用。表述的类型应当有与根据转换的相应类型的表达式相同的类型整数提升。表达式的值应为实参的值。

7.20.4.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中有5个整数字尾: ululllull。不像C中几乎所有其他东西,它们不区分大小写;另外,ulull也可以分别写成lullu(但不能写成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++中也有所不同。

由于提升效果,不可能使用这些后缀将常量限制为任何大小。如果您在intlong都是32位宽的系统上编写281474976710656,则常量将被指定为long long类型,即使您没有这样做。此外,没有后缀强制常量具有shortchar类型。你可以用<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