gpt4 book ai didi

c - C 宏在不同情况下的不同行为

转载 作者:太空狗 更新时间:2023-10-29 14:58:47 26 4
gpt4 key购买 nike

这是代码,

#include<stdio.h>
#include<stdbool.h>

#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))

struct my_struct {
int a, b;
// char c;
};

int main() {
bool cond = 1;
BUILD_BUG_ON((sizeof(struct my_struct) % 8) != 0);
BUILD_BUG_ON(cond);
return 0;
}

如果 sizeof struct 不等于 8,则首次使用 BUILD_BUG_ON(condition) 宏会抛出编译错误,因为条件的计算结果为真。但是即使我提供了真实条件,第二次使用宏也不会引发编译错误。我无法理解这种行为。谁能解释一下?

最佳答案

BUILD_BUG_ON 宏旨在实现编译时断言。

给定一个可以在编译时求值的参数,如果参数不为零 (true),它会导致编译时失败,如果参数不为零 (false),则什么都不做。

它不适用于在运行时评估的参数。

#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))

!! 是两个逻辑“非”运算符;它们的作用是将 0 的值规范化为 0,并将任何非零值规范化为 1

如果结果条件为 1(真),则 1 - 2*!!(condition) 的值为 -1 .如果条件为 0(假),则值为 1

数组的大小不能为负(或零)。一些编译器可能支持零长度数组作为扩展;这个宏确保即使是这样的编译器也能诊断错误。如果大小是常量表达式,则具有负大小的数组违反约束,需要编译时诊断。

如果表达式为假,则没有错误;宏扩展为一个什么都不做的表达式。如果表达式为真并且是常量表达式,则宏的扩展会尝试定义一个负大小的数组,从而导致编译时错误。

如果表达式不是常量,则宏不起作用。 C(C99 及更高版本)允许可变长度数组 (VLA)。零或负长度的 VLA 是不允许的,但定义这样的 VLA 通常无法在编译时检测到。这是未定义的行为——在这种情况下,它可能什么都不做。 (只是为了使事情复杂化,VLA 在文件范围内是不允许的。)

理想情况下,宏应该附有说明如何使用它的文档。该文档应说明参数必须是编译时表达式。

底线:您应该仅将此宏与常量表达式参数一起使用。 (要测试运行时表达式,您可以使用 assert()。)如果您使用具有零值的非常量表达式,则行为未定义;最可能的结果是预期的“断言”不会触发并且不会检测到错误。

关于c - C 宏在不同情况下的不同行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31494179/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com