Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如果0是在c程序中编译的_C_Compilation - Fatal编程技术网

如果0是在c程序中编译的

如果0是在c程序中编译的,c,compilation,C,Compilation,我正在尝试从我的程序中删除未使用的代码-我现在不能删除代码,我只是想先禁用它 假设我有以下代码: if (cond){ doSomething() } 而且cond始终为false,因此永远不会调用doSomething 我想做一些类似的事情: #define REMOVE_UNUSED_CODE 0 if (cond && REMOVE_UNUSED_CODE){ doSomething() } if (cond){ __builtin_unreachable(

我正在尝试从我的程序中删除未使用的代码-我现在不能删除代码,我只是想先禁用它

假设我有以下代码:

if (cond){
  doSomething()
}
而且
cond
始终为false,因此永远不会调用
doSomething

我想做一些类似的事情:

#define REMOVE_UNUSED_CODE 0
if (cond && REMOVE_UNUSED_CODE){
  doSomething()
}
if (cond){
  __builtin_unreachable();
  doSomething()
}
现在,我们很明显(希望对编译器来说)这段代码是未使用的

编译器会删除所有这些
if
条件吗,还是会离开它而永远不会进入


备注:我不能使用
#if 0
来实现此目的

查看您的代码片段

#define REMOVE_UNUSED_CODE 0

if(cond && REMOVE_UNUSED_CODE)
{
    doSomething();
}
编译前,预处理器将
REMOVE\u UNUSED\u代码
替换为
0
。 因此,
if(cond&&0)
将始终被评估为false,并且永远不会执行。所以你可以说,不管cond是什么,它总是假的

所以我更喜欢这样做:

//#define REMOVE_UNUSED_CODE 0

#ifdef REMOVE_UNUSED_CODE
    if(cond)
    {
        doSomething();
    }
#endif

答案取决于编译器的实现。你永远不应该依赖这个

相反,要明确:

#define REMOVE_UNUSED_CODE 0
if (cond && REMOVE_UNUSED_CODE){
#ifndef REMOVE_UNUSED_CODE  
   doSomething()
#endif
}
试一试

相反。 别忘了做一个简单的练习

#define REMOVE_UNUSED_CODE

某处。

你不应该这样做:

假设您有一个带有副作用的函数
bool f(void*input)

然后

if( f(pointer) && false ) { ... }
不评估主体,但应评估
f

if( false && f(pointer) ) { ... }
由于
&&
运算符的快捷规则,不计算f

如果你使用

#define REMOVE_UNUSED_CODE
#ifndef REMOVE_UNUSED_CODE
if( f(pointer) && false ) { }

#endif

整个代码甚至不会编译,也永远不会执行。

GCC将显式删除由常量表达式控制的条件块,而不是使用更粗糙的方法,例如依赖预处理器。尽管使用预处理器
#if
可能会因为在早期阶段删除代码而显得更有效,但实际上,现代优化器在您尽可能多地提供信息时工作得最好(当然,如果您可以避免在不需要添加阶段分离依赖项的地方添加阶段分离依赖项,那么它会使您的程序更干净、更一致)

像这样的决策对于现代编译器来说非常、非常容易做出——即使是非常简单的决策也会执行一些死代码消除;像和GCC这样的强大系统会发现这一点,而且作为人类读者,您可能会错过更复杂的情况(通过跟踪变量的生存期和修改,而不仅仅是查看单个点)


这是除了完整编译的其他优点之外的另一个优点,比如检查
if
中的代码是否有错误(而
#if
对于删除当前系统上可能出错的代码更有用,比如对不存在的平台函数的引用)

对于MSVC来说,它是

对于GCC/Clang,它是

但是,请注意,如果您写了以下内容:

#define REMOVE_UNUSED_CODE 0
if (cond && REMOVE_UNUSED_CODE){
  doSomething()
}
if (cond){
  __builtin_unreachable();
  doSomething()
}
您的条件永远不应计算为
,否则行为未定义。
结合
和删除未使用的代码
内置的不可访问()
确保编译器将删除您的代码。

cond
将在运行时得到评估-您希望在编译时如何知道它?@al Acme我猜OP是在询问
删除未使用的代码
。我不确定编译器的标准,但编译器应该能够识别
删除未使用的代码并保留死角,启用适当的优化。虽然不是很确定。难道你不能试试吗?如果你甚至不知道使用哪种编译器(以及哪种优化级别),也没有人能告诉你“编译器”会做什么你在问。我很有信心大多数启用了优化的编译器将能够计算出
x&&false==false
——假设
cond
可以很容易地确定没有副作用。这显然是针对安全关键系统的事实(如下所述)这有点重要,应该是一个问题-安全/可靠的代码通常不允许以与“常规”代码相同的方式进行优化,因为高端编译器优化有时会引入与最初编写的不同的逻辑(我不认为这会改变这个具体问题的实际答案——这是一个非常基本的优化,第一层——但这是一件非常重要的事情,需要注意)。我不知道这将如何依赖于编译器。如果不优化掉未使用的代码,这将是一个相当愚蠢的编译器。我不认为市场上存在如此糟糕的编译器。我同意,我也会这么认为。但是要绝对肯定,显式是更安全的。如果结果是生或死,你不会这样做消费。如果结果是生死攸关(安全关键应用),这类系统有许多明确禁止此类构造的标准。在安全关键系统中,不允许有任何从未执行过的代码。这里就是这种情况。这是一个安全关键系统,我正在进行覆盖率测试,以删除所有未执行的代码。第一步,如果要禁用所有这些代码,请稍后重新执行如果没有必要的性能问题,请看目标代码。使用用C代码注释程序集的开关。快捷方式仅在C++中进行。c@PhilWilliams,而维基百科(引用标准)则相反。对不起,你是对的。不知道我从哪里得到这个想法的?