如果在c程序中编译0

时间:2021-10-01 11:04:55

I'm trying to removed unused code from my program - I can't delete the code for now, I just want to disable it for a start.

我正在尝试从我的程序中删除未使用的代码 - 我现在无法删除代码,我只想暂停它。

Let's say that I have the following code:

假设我有以下代码:

if (cond){
  doSomething()
}

and cond is always false so doSomething is never called.

和cond总是假的所以doSomething永远不会被称为。

I want to do something like:

我想做的事情如下:

#define REMOVE_UNUSED_CODE 0
if (cond && REMOVE_UNUSED_CODE){
  doSomething()
}

Now this is obvious to us (and hopefully for the compiler) that this code is unused.

现在,对于我们(并且希望编译器)这个代码未被使用是显而易见的。

Will the compiler remove all this if condition or it will leave it and never get in?

编译器是否会删除所有这些条件,否则它将离开它并且永远不会进入?

P.S.: I can't use #if 0 for this purpose

P.S。:我不能将#if 0用于此目的

6 个解决方案

#1


GCC will explicitly remove conditional blocks that have a constant expression controlling them, and the GNU coding standards explicitly recommend that you take advantage of this, instead of using cruder methods such as relying on the preprocessor. Although using preprocessor #if may seem more efficient because it removes code at an earlier stage, in practice modern optimizers work best when you give them as much information as possible (and of course it makes your program cleaner and more consistent if you can avoid adding a phase-separation dependency at a point where it isn't necessary).

GCC将显式删除具有控制它们的常量表达式的条件块,并且GNU编码标准明确建议您利用这一点,而不是使用诸如依赖预处理器之类的更粗糙的方法。尽管使用预处理器#if可能看起来更有效,因为它在早期阶段删除了代码,但在实践中,现代优化器在为您提供尽可能多的信息时效果最佳(当然,如果您可以避免添加,它会使您的程序更清晰,更一致在不必要的点处的相分离依赖性)。

Decisions like this are very, very easy for a modern compiler to make - even the very simplistic TCC will perform some amount of dead-code elimination; powerful systems like LLVM and GCC will spot this, and also much more complex cases that you, as a human reader, might miss (by tracing the lifetime and modification of variables beyond simply looking at single points).

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

This is in addition to other advantages of full compilation, like the fact that your code within the if will be checked for errors (whereas #if is more useful for removing code that would be erroneous on your current system, like references to nonexistent platform functions).

这是完全编译的其他优点之外,例如if中的代码将被检查错误(而#if对于删除当前系统中错误的代码更有用,例如对不存在的平台函数的引用)。

#2


Try

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

Instead. Don't forget to do a

代替。别忘了做一个

#define REMOVE_UNUSED_CODE

somewhere.

#3


The answer depends on the implementation of the compiler. You should never depend on this.

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

Instead be explicit:

而是明确:

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

#4


Looking at this snippet of your code

看看你的代码片段

#define REMOVE_UNUSED_CODE 0

if(cond && REMOVE_UNUSED_CODE)
{
    doSomething();
}

REMOVE_UNUSED_CODE is replaced with 0 by preprocessor before compilation. So if(cond && 0) will always be evaluated as false and will never be executed. So you can say, irrespective of what cond is, it will always be false.

编译前,REMOVE_UNUSED_CODE由预处理器替换为0。因此,如果(cond && 0)将始终被评估为false并且永远不会被执行。所以你可以说,无论cond是什么,它总是假的。

So I'd rather prefer it doing this way:

所以我宁愿这样做:

//#define REMOVE_UNUSED_CODE 0

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

#5


You should not do it that way:

你不应该这样做:

Suppose you have a function bool f(void* input) with side effects.

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

Then with

if( f(pointer) && false ) { ... }

the body is not evaluated, but f should be.

身体没有评估,但应该是。

In the case of

如果是

if( false && f(pointer) ) { ... }

f is not evaluated because of the short-cut rule of the &&operator.

由于&&运算符的快捷方式规则,因此不评估f。

If you use

如果你使用

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

#endif

the whole code is not even compiled in and will never be executed.

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

#6


Not a direct answer, but may be helpful. There are compiler-specific intrinsics to do code removal.

不是直接的答案,但可能会有所帮助。有特定于编译器的内在函数来执行代码删除。

For MSVC, it is __assume(0)

对于MSVC,它是__assume(0)

For GCC/Clang, it is __builtin_unreachable().

对于GCC / Clang,它是__builtin_unreachable()。

Notice, however, that if you write something like:

但请注意,如果你写的东西如下:

if (cond){
  __builtin_unreachable();
  doSomething()
}

Your condition should never evaluate to true, otherwise behavior is undefined. Combining both && REMOVE_UNUSED_CODE and __builtin_unreachable() ensures that your code will be removed by the compiler.

你的病情永远不应该评估为真,否则行为是不确定的。将&& REMOVE_UNUSED_CODE和__builtin_unreachable()组合在一起可确保编译器删除您的代码。

#1


GCC will explicitly remove conditional blocks that have a constant expression controlling them, and the GNU coding standards explicitly recommend that you take advantage of this, instead of using cruder methods such as relying on the preprocessor. Although using preprocessor #if may seem more efficient because it removes code at an earlier stage, in practice modern optimizers work best when you give them as much information as possible (and of course it makes your program cleaner and more consistent if you can avoid adding a phase-separation dependency at a point where it isn't necessary).

GCC将显式删除具有控制它们的常量表达式的条件块,并且GNU编码标准明确建议您利用这一点,而不是使用诸如依赖预处理器之类的更粗糙的方法。尽管使用预处理器#if可能看起来更有效,因为它在早期阶段删除了代码,但在实践中,现代优化器在为您提供尽可能多的信息时效果最佳(当然,如果您可以避免添加,它会使您的程序更清晰,更一致在不必要的点处的相分离依赖性)。

Decisions like this are very, very easy for a modern compiler to make - even the very simplistic TCC will perform some amount of dead-code elimination; powerful systems like LLVM and GCC will spot this, and also much more complex cases that you, as a human reader, might miss (by tracing the lifetime and modification of variables beyond simply looking at single points).

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

This is in addition to other advantages of full compilation, like the fact that your code within the if will be checked for errors (whereas #if is more useful for removing code that would be erroneous on your current system, like references to nonexistent platform functions).

这是完全编译的其他优点之外,例如if中的代码将被检查错误(而#if对于删除当前系统中错误的代码更有用,例如对不存在的平台函数的引用)。

#2


Try

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

Instead. Don't forget to do a

代替。别忘了做一个

#define REMOVE_UNUSED_CODE

somewhere.

#3


The answer depends on the implementation of the compiler. You should never depend on this.

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

Instead be explicit:

而是明确:

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

#4


Looking at this snippet of your code

看看你的代码片段

#define REMOVE_UNUSED_CODE 0

if(cond && REMOVE_UNUSED_CODE)
{
    doSomething();
}

REMOVE_UNUSED_CODE is replaced with 0 by preprocessor before compilation. So if(cond && 0) will always be evaluated as false and will never be executed. So you can say, irrespective of what cond is, it will always be false.

编译前,REMOVE_UNUSED_CODE由预处理器替换为0。因此,如果(cond && 0)将始终被评估为false并且永远不会被执行。所以你可以说,无论cond是什么,它总是假的。

So I'd rather prefer it doing this way:

所以我宁愿这样做:

//#define REMOVE_UNUSED_CODE 0

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

#5


You should not do it that way:

你不应该这样做:

Suppose you have a function bool f(void* input) with side effects.

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

Then with

if( f(pointer) && false ) { ... }

the body is not evaluated, but f should be.

身体没有评估,但应该是。

In the case of

如果是

if( false && f(pointer) ) { ... }

f is not evaluated because of the short-cut rule of the &&operator.

由于&&运算符的快捷方式规则,因此不评估f。

If you use

如果你使用

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

#endif

the whole code is not even compiled in and will never be executed.

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

#6


Not a direct answer, but may be helpful. There are compiler-specific intrinsics to do code removal.

不是直接的答案,但可能会有所帮助。有特定于编译器的内在函数来执行代码删除。

For MSVC, it is __assume(0)

对于MSVC,它是__assume(0)

For GCC/Clang, it is __builtin_unreachable().

对于GCC / Clang,它是__builtin_unreachable()。

Notice, however, that if you write something like:

但请注意,如果你写的东西如下:

if (cond){
  __builtin_unreachable();
  doSomething()
}

Your condition should never evaluate to true, otherwise behavior is undefined. Combining both && REMOVE_UNUSED_CODE and __builtin_unreachable() ensures that your code will be removed by the compiler.

你的病情永远不应该评估为真,否则行为是不确定的。将&& REMOVE_UNUSED_CODE和__builtin_unreachable()组合在一起可确保编译器删除您的代码。