stdint.h 中这个神秘的宏加号是什么?
请看我的代码:
#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;
}
我发现
中的宏定义是:
#define INT8_C(val) ((int8_t) + (val))
这个加号的含义或意义是什么?
Please see my code:
#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;
}
I find that the macro definition in <stdint.h>
is:
#define INT8_C(val) ((int8_t) + (val))
What is the meaning or significance of this plus sign?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
代码片段:
是一个表达式,它采用值
78
,应用一元+
,然后将其转换为int8_t< /code> 输入,然后扔掉它。它与合法表达式没有真正的区别:
它也计算表达式然后丢弃结果(尽管如果编译器可以判断没有副作用,则这些表达式可能会被优化为不存在)。
这些“裸”表达式在 C 中完全有效,并且通常仅当它们具有副作用时才有用,例如使用
i++
,它会计算i
并将其与副作用一起丢弃因为它增加了价值。您应该使用该宏的方式更像是:
看似多余的一元
+
运算符的原因可以在标准中找到。引用 C996.5.3.3 一元算术运算符 /1
:并且,在
6.2.5 类型,/18
中:换句话说,一元
+
阻止您使用宏中的所有其他数据类型,例如指针、复数或结构。最后,您的:
代码片段不起作用的原因是因为它不是同一件事。这个变量开始声明一个
signed char
类型的变量,但当它到达+
时就会卡住,因为这不是合法的变量名。为了使其与您的工作片段等效,您可以使用:这是值
+78
到类型signed char
的转换。而且,根据 C99
7.8.14 Macros for integer Constants /2
,您还应该小心在这些宏中使用非常量,它们不能保证有效:6.4.4.1
只是指定各种整数格式(十进制/八进制/十六进制)以及各种后缀(U
、UL
、ULL
、L
、LL
以及小写等效项,具体取决于类型)。最重要的是它们必须是常量而不是变量。例如,
glibc
具有:这将允许您的
INT8_C
宏正常工作,但文本INT64_C(val)
将被预处理为valL
或valLL
,这两者都是您不想要的。The snippet:
is an expression, one that takes the value
78
, applies the unary+
, then casts that to anint8_t
type, before throwing it away. It is no real different to the legal expressions:which also evaluate the expressions then throw away the result (though these will possibly be optimised out of existence if the compiler can tell that there are no side effects).
These "naked" expressions are perfectly valid in C and generally useful only when they have side effects, such as with
i++
, which calculatesi
and throws it away with the side effect being that it increments the value.The way you should be using that macro is more along the lines of:
The reason for the seemingly redundant unary
+
operator can be found in the standard. Quoting C996.5.3.3 Unary arithmetic operators /1
:And, in
6.2.5 Types, /18
:In other words, the unary
+
prevents you from using all the other data types in the macro, such as pointers, complex numbers or structures.And, finally, the reason your:
snippet doesn't work is because it's not the same thing. This one is starting to declare a variable of type
signed char
but chokes when it gets to the+
since that's not a legal variable name. To make it equivalent to your working snippet, you would use:which is the casting of the value
+78
to typesigned char
.And, as per C99
7.8.14 Macros for integer constants /2
, you should also be careful with using non-constants in those macros, they're not guaranteed to work:6.4.4.1
simply specifies the various integer formats (decimal/octal/hex) with the various suffixes (U
,UL
,ULL
,L
,LL
and the lower-case equivalents, depending on the type). The bottom line is that they have to be constants rather than variables.For example,
glibc
has:which will allow your
INT8_C
macro to work fine but the textINT64_C(val)
would be pre-processed into eithervalL
orvalLL
, neither of which you would want.似乎每个人都错过了这里一元加运算符的要点,即使结果在
#if
预处理器指令中有效。给定:指令:
扩展为:
从而按预期工作。这是因为
#if
指令中任何未#define
的符号都会扩展为0
。如果没有一元加号(在
#if
指令中变成二进制加号),表达式在#if
指令中将无效。Seems everyone has missed the point of the unary plus operator here, which is to make the result valid in
#if
preprocessor directives. Given:the directives:
expand as:
and thus work as expected. This is due to the fact that any un
#define
d symbol in an#if
directive expands to0
.Without the unary plus (which becomes a binary plus in
#if
directives), the expression would not be valid in#if
directives.它是一个一元
+
运算符。它产生其操作数的值,但它只能应用于算术类型。这里的目的是防止在指针类型的表达式上使用INT8_C
。但是你的语句表达式
有未定义的行为。
INT8_C()
的参数必须是“一个无后缀的整型常量...其值不超过相应类型的限制”(N1256 7.18.4)。这些宏的目的是让您编写类似INT64_C(42)
的内容,并在int64_t
为long 时将其扩展为
,或者如果42L
int64_t
是 `long long,则为42LL
,依此类推。但是在您自己的代码中编写
或
是完全合法的。
编辑:
问题中
INT8_C()
的定义:在C99中有效,但根据后来的N1256草案不符合,因为技术勘误之一。
最初的 C99 标准,第 7.18.4.1p2 节说:
N1256 将其更改为(第 3 段):
此更改是为了响应缺陷报告#209。
EDIT2:但是请参阅 R.. 的回答;它实际上在 N1256 中有效,原因很不明朗。
It's a unary
+
operator. It yields the value of its operand, but it can be applied only to arithmetic types. The purpose here is to prevent the use ofINT8_C
on an expression of pointer type.But your statement expression
has undefined behavior. The argument to
INT8_C()
is required to be "an unsuffixed integer constant ... with a value that does not exceed the limits for the corresponding type" (N1256 7.18.4). The intent of these macros is to let you write something likeINT64_C(42)
and have it expand to42L
ifint64_t
islong
, or to42LL
ifint64_t
is `long long, and so forth.But writing either
or
in your own code is perfectly legal.
EDIT:
The definition for
INT8_C()
in the question:is valid in C99, but is non-conforming according to the later N1256 draft, as a result of a change in one of the Technical Corrigenda.
The original C99 standard, section 7.18.4.1p2, says:
N1256 changed this to (paragraph 3):
The change was made in response to Defect Report #209.
EDIT2: But see R..'s answer; it's actually valid in N1256, for quite obscure reasons.
这是一元加号。
它只能做两件事。
它将所谓的常见算术转换应用于操作数。这为结果建立了一个公共实数类型。如果结果即将转换为特定的内容,我想不出有任何理由强制执行此操作。
它将操作数限制为定义算术运算符的类型。这似乎是更可能的原因。
That's a unary plus.
There are only two things it could be doing.
It applies what are know as the usual arithmetic conversions to the operand. This establishes a common real type for a result. I can't think of any reason to force this if the result is about to be cast into something specific.
It restricts the operand to types for which arithmetic operators are defined. This seems like the more likely reason.