суббота, 5 июля 2008 г.

Операции над указателями...

Долгая дискуссия заставила призадуматься...

С одной стороны в исходниках 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)
addl $20, -8(%ebp)
add есть, а вот sub не наблюдаю...

Эта ерунда всплыла у меня когда я тшетно пытался посмотреть код, генерируемый выражениями argc + argv - 1, argv + argc - 1 с помощью BOOST_ASSERT(argc + argv - 1 == argv + argc - 1);. Выражение оказывалось истинным, и BOOST_ASSERT вообще не генерировал никакого кода, не смотря на -O0. Дык он и свертку выполнил безо всякого разрешения.

Может быть у gcc есть какой нибудь волшебный ключик, который позволяет разрешить генерацию недостижимого кода? не знаю точно...