Будет ли компилятор оптимизировать это
Скажите, что у меня есть что-то подобное в коде 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, например. Поэтому любой здравомыслящий компилятор С++ обнаруживает и оптимизирует явно мертвый код этого типа, даже если вы компилируете без указания параметров оптимизации.