Будет ли компилятор оптимизировать это

Скажите, что у меня есть что-то подобное в коде C. Я знаю, что вместо этого вы можете использовать #define, чтобы компилятор не скомпилировал его, но просто из любопытства я спрашиваю, будет ли компилятор также разбираться в этой штуке.

Я думаю, что это еще более важно для Java Compiler, поскольку он не поддерживает #define.

const int CONDITION = 0;
........
// Will the compiler compile this?
if ( CONDITION )
{

}
.......

Ответ 1

в Java, код внутри if даже не будет частью скомпилированного кода. Он должен компилироваться, но он не будет записан в скомпилированный байт-код. На самом деле это зависит от компилятора, но я не знаю компилятора, который его не оптимизирует. правила определены в JLS:

Оптимизирующий компилятор может понять, что утверждение x = 3; никогда быть выполненным и может отказаться от кода для этого утверждения из сгенерированный файл класса, но утверждение x = 3; не рассматривается как "недоступный" в техническом смысле, указанном здесь.

Обоснование этого различного обращения заключается в том, чтобы позволить программистам определить "переменные флага", такие как:

static final boolean DEBUG = false;

а затем напишите код, например:

if (DEBUG) { x=3; }

Идея состоит в том, что должно быть возможно изменить значение DEBUG от false до true или от true до false, а затем скомпилировать код правильно, без каких-либо изменений в тексте программы.

Не знаю о C.

Ответ 2

Во-первых, Java не допускает небулевых в условных выражениях, таких как C (if, while и т.д.). Кроме того, если у вас есть "постоянное выражение" в ваших тегах if, компилятор предупредит вас, что вы сравниваете одинаковые выражения, поэтому я уверен, что он оптимизирован. Например,

    final int i = 1;
    if (1 == i) { // warning
        System.out.println("HI");
    }

Ответ 3

Вместо того, чтобы задавать такие простые вопросы (где единственный правильный ответ: "Попробуйте с вашим компилятором" ) - почему бы просто не попробовать?

public class Test {
    public static void main(String[] args) {
        if (true) {
            System.out.println("Yep");
        }
        boolean var = false;
        if (var) {
            System.out.println("Nope");
        }
        final boolean var2 = false;
        if (var2) {
            System.out.println("Nope");
        }
    }
}

javac .\Test.java 
javap -c Test
Compiled from "Test.java"
public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #3                  // String Yep
       5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: iconst_0
       9: istore_1
      10: iload_1
      11: ifeq          22
      14: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      17: ldc           #3                  // String Yep
      19: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      22: return
}

Вам не нужно много знать о байт-коде Java/С# или сборке, чтобы понять, что происходит. И теперь идите и попробуйте то же самое для С#..

Ответ 4

Я просто быстро проверил следующий фрагмент кода

public class Test {
    private static final boolean flag = true;

    public static void main(String[] args) throws InterruptedException {

        if(flag){
            System.out.println("1");
            System.out.println("1");
            System.out.println("1");
            System.out.println("1");
            System.out.println("1");
            System.out.println("1");
            System.out.println("1");
            System.out.println("1");
            System.out.println("1");        
        }

    }

}

когда флаг = true, результирующий размер файла класса составляет 708

когда флаг = false. итоговый размер файла файла - 462

что подразумевает, что компиляция, безусловно, делает оптимизацию для статических конечных значений

Ответ 5

Я могу вспомнить сценарии в своих программах на Java и С#, где это было (оптимизируйте). Но я также знаю, что это сильно зависит от параметров компилятора, поэтому сценарий слишком неспецифичен.

В сценарии Java мы имели значения const в одном исходном файле Java, в то время как они использовались в другом классе (файле). То, что произошло, когда мы только что изменили и перекомпилировали файл со значениями const, ничего не изменилось в потоке используемых частей. Нам пришлось перекомпилировать весь проект (который является доказательством его оптимизации).

Ответ 6

Ниже приведено описание языка C. Я не знаю, как это работает Java.

Так как int определяется как const, if (i) становится инструкцией no-op. Умный компилятор должен иметь возможность оптимизировать этот пустой оператор if.

Пример: VC 2008

Непустой {} с выражением if:

const int i = 1;
// mov dword ptr [i], 1
if (i)
// mov eax, 1
// test eax, eax
// je wmain+35h
{
   int j = 2;
   // move dword ptr [j], 2
}
// ..

Пусто {} с инструкцией if:

const int i = 1;
// mov dword ptr [i], 1
if (i)
{
}
// ..

Ответ 7

Компилятор java должен обнаруживать явно недостижимый код, что требует языкового требования. Таким образом, следующий код будет компилироваться без ошибок:

static final boolean flag = true; 

public static void main(String[] args) {
    final String msg;
    if (flag)
        msg = "true";
    if (!flag)
        msg = "false";
    System.out.println(msg);
}

Обратите внимание, что msg является окончательным, но компилятор не жалуется, что msg не инициализирован, и он не жалуется, что он инициализируется дважды. Большинство компиляторов не будут записывать мертвый код в файл класса. Но даже если JIT оптимизирует его.

С++ также имеет понятие констант времени компиляции. Константа int - это константа времени компиляции, поэтому ее можно использовать как аргумент шаблона nontype, например. Поэтому любой здравомыслящий компилятор С++ обнаруживает и оптимизирует явно мертвый код этого типа, даже если вы компилируете без указания параметров оптимизации.