片段:
((int8_t) + (78));
是一个表达式,它接受 value 78
,应用 unary +
,然后将其转换为int8_t
类型,然后将其丢弃。它与法律表达没有真正的不同:
42;
a + 1;
它还评估表达式然后丢弃结果(尽管如果编译器可以判断没有副作用,这些可能会被优化不存在)。
这些“裸”表达式在 C 中完全有效,并且通常仅在它们具有副作用时才有用,例如 with i++
,它计算i
并丢弃它,副作用是它增加值。
您应该使用该宏的方式更像是:
int8_t varname = INT8_C (somevalue);
+
可以在标准中找到看似多余的一元运算符的原因。引用 C99 6.5.3.3 Unary arithmetic operators /1
:
一元 + 或 - 运算符的操作数应具有算术类型;
并且,在6.2.5 Types, /18
:
整数和浮点类型统称为算术类型。
换句话说,一元+
阻止您使用宏中的所有其他数据类型,例如指针、复数或结构。
最后,您的原因是:
signed char + 78;
片段不起作用是因为它不是同一件事。这个开始声明一个类型的变量,signed char
但是当它到达时会窒息,+
因为这不是一个合法的变量名。为了使其等同于您的工作片段,您将使用:
(signed char) + 78;
这是将值+78
转换为 type 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
这将使您的INT8_C
宏可以正常工作,但文本INT64_C(val)
将被预处理为valL
or valLL
,您都不需要。