С одной стороны в исходниках gcc я явно обнаружил обмен индекса и указателя, в случае операций с массивами (gcc/gcc/c-types.c):
if (TREE_CODE (TREE_TYPE (array)) != ARRAY_TYPEНо загадочности на этом не закончились. На самом деле компилятору действительно пофиг что с чем складывать. указатель с индексом или индекс с указателем, результатом всеравно будет указатель на элемент.
&& TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE)
{
tree temp;
if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE)
{
error ("subscripted value is neither array nor pointer");
return error_mark_node;
}
temp = array;
array = index;
index = temp;
swapped = true;
}
char s[] = "hello";Так вот второе выражение смущает меня больше всего.
int idx = 3;
assert (*(s + idx) == 'l' && *(idx + s) == 'l');
Понятно что в математике от перемены мест слагаемых сумма не изменяется. Но и простым преобразованием этого объяснить тоже не получается. Попытка сложить два указателя вызовет ошибку компиляции. Модификация указателя всегда производится кратно размеру его элементов. В то время как модификация целого значения всегда кратна единице.
А компилятор, как партизан упорно молчит. Хоть бы варнинг чтоли сделали какой.
Вообще компилятор во многих случаях молчит. Я вот до сих пор считал, что удаление недостижимого кода - это оптимизация. И при компиляции без оптимизации компилятор должен тупо генерить все что написано. Но это оказалось не так.
int i = 10;
if (1) i += 20;
if (0) i -= 30;
$ gcc -O0 -S ...
movl $10, -8(%ebp)add есть, а вот sub не наблюдаю...
addl $20, -8(%ebp)
Эта ерунда всплыла у меня когда я тшетно пытался посмотреть код, генерируемый выражениями
argc + argv - 1, argv + argc - 1
с помощью BOOST_ASSERT(argc + argv - 1 == argv + argc - 1);
. Выражение оказывалось истинным, и BOOST_ASSERT вообще не генерировал никакого кода, не смотря на -O0. Дык он и свертку выполнил безо всякого разрешения.Может быть у gcc есть какой нибудь волшебный ключик, который позволяет разрешить генерацию недостижимого кода? не знаю точно...
8 коммент.:
я тоже когда-то с подобной проблемой столкнулся - volatile тогда помог, правда то был случай не с недостижимым кодом...
Но почему он вообще оптимизирует??? не знаю как VS, gcc вроде бы такой ерундой стал страдать сравнительно недавно. может быть с gcc4...
Может быть, тривиальные виды оптимизации переросли в нечто естественное, без которого даже O0 не может существовать, а им на смену пришла векторизация... :)
Попробуй
int i = 10;
volatile a = 1;
if (a == 1) i += 20;
if (a == 0) i -= 30;
Совершенно недостижимый код компилировать не логично, и правильно что не компилируется. Атрибут volatile делает код хотябы потенциально достижимым, поэтому есть шанс что скомпилируется.
Свертка выражений и удаление недостижимого кода - это все виды оптимизации.. Значит если я говорю что оптимизация запрещена - надо все эти возможности отключить...
А то получается что
отключай оптимизацию, не отключай, всеравно она оптимизирует... :(
Кроме того логичность должна диктоваться необходимостью... А если мне необходимо отключать оптимизацию, то вряд ли мне сможет помешать недостижимый код, удалять его нелогично.
Удаление недостижимого кода - не обязательно результат оптимизации. Возможно, тут просто некомпиляция. Нет точки входа - нет и кода, если это противоречит логики кодогенератора (на уровне алгоритма кодогенерации).
А еще он (gcc) функции инлайнит хотя его об этом не просили...
Хотя надо сказать что при O0 он не осмеливается этого делать :)
Так вот второе выражение смущает меня больше всего.
Стандартный Си. На некоторых компиляторах вообще этот код верен:
int i, *s;
i = i[*s];
так как i[*s] автоматом преобразуется в *(i + s), причем эта функциональность явно описывается как фича.
А компилятор, как партизан упорно молчит. Хоть бы варнинг чтоли сделали какой.
С какой стати-то?
И при компиляции без оптимизации компилятор должен тупо генерить все что написано.
Это в MSVC так... чтобы отлаживать было проще, потому как оптимизатор код может сильно ворочать.
Тьфу ты!
int i;
int *s;
i = i[s];
Прошу прощения.
Это и сейчас верно, кстати.
Отправить комментарий