请看我的代码:
#include <stdint.h>
int main(int argc, char *argv[])
{
unsigned char s = 0xffU;
char ch = 0xff;
int val = 78;
((int8_t) + (78)); /*what does this mean*/
INT8_C(val); /*equivalent to above*/
signed char + 78; /*not allowed*/
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我发现宏定义<stdint.h>是:
#define INT8_C(val) ((int8_t) + (val))
Run Code Online (Sandbox Code Playgroud)
这个加号是什么意思或含义?
pax*_*blo 27
片段:
((int8_t) + (78));
Run Code Online (Sandbox Code Playgroud)
是一个表达式,一个取值78,应用一元+,然后将其转换为一个int8_t类型,然后扔掉它.这与法律表达没有什么不同:
42;
a + 1;
Run Code Online (Sandbox Code Playgroud)
还会评估表达式,然后抛弃结果(尽管如果编译器可以判断出没有副作用,这些可能会被优化掉).
这些"裸"表达式在C中完全有效,并且通常仅在它们具有副作用时才有用,例如with i++,其计算i并将其抛出,副作用是它增加值.
您应该使用该宏的方式更符合以下方面:
int8_t varname = INT8_C (somevalue);
Run Code Online (Sandbox Code Playgroud)
+在标准中可以找到看似冗余的一元算子的原因.引用C99 6.5.3.3 Unary arithmetic operators /1:
一元+或 - 运算符的操作数应具有算术类型;
并且,在6.2.5 Types, /18:
整数和浮点类型统称为算术类型.
换句话说,一元组会+阻止您使用宏中的所有其他数据类型,例如指针,复数或结构.
最后,你的原因是:
signed char + 78;
Run Code Online (Sandbox Code Playgroud)
片段不起作用是因为它不是一回事.这个开始声明一个类型的变量,signed char但是当它到达时就会扼流,+因为那不是合法的变量名.要使其等效于您的工作代码段,您可以使用:
(signed char) + 78;
Run Code Online (Sandbox Code Playgroud)
这是+78要输入值的类型signed char.
并且,根据C99 7.8.14 Macros for integer constants /2,您还应该小心在这些宏中使用非常量,它们不能保证工作:
这些宏的任何实例中的参数都应是未填充的整数常量(如6.4.4.1中所定义),其值不超过相应类型的限制.
6.4.4.1简单地规定了不同的整数格式(十进制/八进制/十六进制)与各种后缀(U,UL,ULL,L,LL和小写当量,取决于类型).底线是它们必须是常数而不是变量.
例如,glibc有:
# define INT8_C(c) c
# define INT16_C(c) c
# define INT32_C(c) c
# if __WORDSIZE == 64
# define INT64_C(c) c ## L
# else
# define INT64_C(c) c ## LL
# endif
Run Code Online (Sandbox Code Playgroud)
这将允许你的INT8_C宏工作正常,但文本INT64_C(val)将被预处理成任何一个valL或valLL两个你想要的.
R..*_*R.. 18
似乎每个人都错过了这里的一元加运算符,这是为了使结果在#if预处理器指令中有效.鉴于:
#define INT8_C(val) ((int8_t) + (val))
Run Code Online (Sandbox Code Playgroud)
指令:
#define FOO 1
#if FOO == INT8_C(1)
Run Code Online (Sandbox Code Playgroud)
扩展为:
#if 1 == ((0) + (1))
Run Code Online (Sandbox Code Playgroud)
因此按预期工作.这是因为指令中的任何un #defined符号都#if扩展为0.
如果没有一元加号(在#if指令中变为二进制加),表达式在#if指令中将无效.
Kei*_*son 10
这是一个一元的+运营商.它产生其操作数的值,但它只能应用于算术类型.这里的目的是防止在INT8_C指针类型的表达式上使用.
但你的陈述表达
INT8_C(val);
Run Code Online (Sandbox Code Playgroud)
有未定义的行为.参数to INT8_C()必须是"一个不固定的整数常量......其值不超过相应类型的限制"(N1256 7.18.4).这些宏的目的是让你喜欢写东西INT64_C(42),并把它扩大到42L如果int64_t是long,或者42LL如果int64_t是`很长很长,等等.
但是要么写作
((int8_t) + (78));
Run Code Online (Sandbox Code Playgroud)
要么
((int8_t) + (val));
Run Code Online (Sandbox Code Playgroud)
在你自己的代码中是完全合法的.
编辑:
问题中的定义INT8_C():
#define INT8_C(val) ((int8_t) + (val))
Run Code Online (Sandbox Code Playgroud)
在C99中有效,但根据后来的N1256草案,由于其中一项技术勘误更改,因此不符合要求.
最初的C99标准,第7.18.4.1p2节,说:
宏INT***N* _C**(值)应扩展为带有指定值的有符号整数常量,并输入int_least***N* _t**.
N1256改为(第3段):
其中一个宏的每次调用都应扩展为适合在#if预处理指令中使用的整数常量表达式.表达式的类型应与根据整数提升转换的相应类型的表达式具有相同的类型.表达式的值应该是参数的值.
该变更是针对缺陷报告#209进行的.
EDIT2:但是看看R ..的回答; 由于非常模糊的原因,它在N1256中实际上是有效的.