- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我的系统使用 libc6 2.29。在 /usr/include/assert.h
我可以找到 assert()
宏的定义:
/* The first occurrence of EXPR is not evaluated due to the sizeof,
but will trigger any pedantic warnings masked by the __extension__
for the second occurrence. The ternary operator is required to
support function pointers and bit fields in this context, and to
suppress the evaluation of variable length arrays. */
# define assert(expr) \
((void) sizeof ((expr) ? 1 : 0), __extension__ ({ \
if (expr) \
; /* empty */ \
else \
__assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION); \
}))
我想知道为什么要使用逗号运算符,以及“由于 sizeof 而未评估 EXPR 的第一次出现
”是什么意思。
使用下面的定义会出现什么问题:
# define assert(expr) \
({ \
if (expr) \
; /* empty */ \
else \
__assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION); \
})
编辑:
如果 expr
为真,运算符 ({ }) 会得到什么值?
是否可以重写 assert() 的定义如下?
# define assert(expr) \
((void) sizeof ((expr) ? 1 : 0), __extension__ ({ \
if (!expr) \
__assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION); \
}))
最后一个定义的问题在哪里?
最佳答案
我不是 100% 确定这一点,但我会试一试。
首先,让我们回顾一下这里使用的一些东西。
逗号运算符丢弃前 n-1 个表达式结果并返回第 n 个结果。它通常用作 sequence point ,因为它保证表达式将按顺序计算。
这里使用 __extension__
,它是一个 GNU LibC 宏,用于在指定迂腐警告的编译环境下,通过 -ansi
或 -pedantic
等屏蔽 header 中有关 GNU 特定扩展的任何警告。通常在这样的编译器,使用特定于编译器的扩展会抛出警告(如果您在 -Werror
下运行,这很常见,则会引发错误),但由于在使用 GNU 库和编译器的情况下,libc 允许自己使用一些可以安全地进行扩展。
现在,由于实际的断言逻辑可能使用 GNU 扩展(如使用 __extension__
所示,表达式本身可能已根据其语义(即传递给 assert(expr)
的表达式)引发的任何实际警告将是被屏蔽,因为该表达式在语义上位于 __extension__
block 内,因此被屏蔽。
因此,需要一种方法让编译器有机会显示这些警告,但不评估实际的表达式(因为表达式可能有副作用,并且双重评估可能会导致不良行为)。
您可以使用 sizeof
运算符执行此操作,该运算符接受一个表达式,查看其类型,并找出它占用的字符数 - 而无需实际计算表达式。
例如,如果我们有一个函数 int blow_up_the_world()
,那么表达式 sizeof(blow_up_the_world())
将计算表达式结果的大小(在本例中为 int
),而无需实际计算表达式。在这种情况下使用 sizeof()
意味着世界实际上不会被炸毁。
但是,如果传递给 expr
的 assert(expr)
包含会触发编译器警告的代码(例如,在 -pedantic
或 -ansi
模式下使用扩展),即使代码在 sizeof()
中,编译器仍会显示这些警告 - 警告否则将被屏蔽在 __extension__
block 内。
接下来,我们看到他们没有将 expr
直接传递给 sizeof
,而是使用三元。那是因为三元的类型是两个结果表达式所具有的任何类型——在本例中是 int
或等价物。这是因为将某些东西传递给 sizeof
会产生一个运行时值——即在 variable length arrays 的情况下——这可能产生不良影响,或者可能产生错误,例如当 passing sizeof
a function name 时。
最后,他们想要所有这些,但在实际评估之前,他们希望将 assert()
保留为表达式,因此他们没有使用 do{}while()
block 或类似的东西(这最终会导致 assert()
成为语句),而是使用了逗号运算符丢弃第一个 sizeof()
技巧的结果。
关于c - libc6 : comma operator in assert macro definition,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56314110/
测试返回类型为 bool 的方法时。 你应该: expected = true; Assert.AreEqual(expected, actual); 或 Assert.IsTrue(actual);
我最近在编写新的 NUnit 测试时尝试使用 Assert.Equals() 方法。执行此方法时会抛出一个 AssertionException ,说明Assert.Equals 不应该用于断言。 乍
在 Chai 断言库中,当我们已经有了“assert.deepEqual()”时,“assert.equal()”有什么用"和 "assert.strictEqual()"用于严格和深度相等断言?还提
有没有办法断言 puppet 中的变量(或更具体地说,事实)具有特定值,如果没有则中止安装? 对于背景,情况如下: 在大多数情况下,我可以引用主机名,但有时我需要使用 IP 地址。例如,我们的日志收集
喜欢什么: Assert.That(obj.Foo, Is.EqualTo(true)) 或 Assert.True(obj.Foo) 对我来说,这两个断言是等价的,那么应该首选哪个? 最佳答案 在这
如何在 xUnit 中找到多个断言或软断言?我发现 Nunit 有以下能力,试图在 xUnit 中找到类似的选项。 Assert.Multiple(() => { Assert.AreEqua
有什么区别: Assert.Equals和 Assert.AreEqual Assert.NotNull和 Assert.IsNotNull ... ? 最佳答案 Assert.Equals 是一个对
我想写一个像这样工作的断言函数: //the following expression outputs "assertion failed" to std::err and then terminat
有人可以指出差异吗? 以上确实是我的问题,但是如果您也可以与他们分享您的经验以及您为什么使用其中一个。 最佳答案 它们只是两个不同的库,因此只需查看功能,尤其是报告功能,然后选择即可。 因为我是 的作
我无法找到断言 1 失败但断言 2 通过的原因: var a = Test.test1; var b = Test.test1; a.Should().BeSameAs(b); //1 Assert.
我正在为每个步骤使用 NUnit 断言运行自动化 BDD 步骤,即 Then And 我的 UI 测试。 NUnit 断言仅限于每个方法。这意味着如果方法中的断言失败,则不会运行其他步骤。 我正在考虑
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我只是在寻找一些示例,说明何时适合使用 Assert.Catch 或 Assert.Throws 断言单元测试中抛出的任何异常。我知道我也可以使用 ExpectedException,但我特别想知道“
Assert.AreEqual 和 Assert.AreSame 有什么区别? 最佳答案 这意味着 AreSame() 检查它们是否是完全相同的对象 - 如果引用指示内存中的相同对象。 AreEqua
在C#中,有什么区别 Assert.AreNotEqual 和 Assert.AreNotSame 最佳答案 这里给出的几乎所有答案都是正确的,但可能值得举个例子: public static str
我曾经在 NUnit 中使用过它们,它们非常有用。知道如何做类似的事情吗? 编辑,代码示例: bool condition = false;//would be nice not to have th
关于Arrange-Act-Assert的经典测试模式,我经常发现自己在 Act 之前添加了反断言。这样我就知道传递的断言确实是作为操作的结果传递的。 我认为它类似于红绿重构中的红色,只有当我在测试过
每当我创建断言时,Eclipse 都会建议我从这两个包之一导入它。 例如,当我尝试使用 assertArrayEquals() 比较数组时Eclipse 建议从其中之一导入它 org.junit.As
每当我创建断言时,Eclipse 都会建议我从这两个包之一导入它。 例如,当我尝试使用 assertArrayEquals() 比较数组时Eclipse 建议从其中之一导入它 org.junit.As
我是一名优秀的程序员,十分优秀!