С указатели и ||операторы - PullRequest
       24

С указатели и ||операторы

1 голос
/ 10 сентября 2011

Мне просто интересно, является ли это "хорошим" кодом для программы на C89.

obj_ptr = (obj*) (ptr1 || ptr2);

По существу то, что он делает (по крайней мере, в GCC на моем компьютере), устанавливает obj_ptr как ptr1, если ptr1! =NULL и ptr2 в противном случае.

Я огляделся по сторонам и не могу понять, правильно ли это, но судя по тому, что ||Оператор должен преобразовать указатели в целые числа, а затем я должен привести их обратно - намек на плохой стиль.

Если это плохой стиль или непереносимый, и есть ли лучшее и (надеюсь) такое же краткое решение?

РЕДАКТИРОВАТЬ: Моя основная проблема в том, является ли написанный мною код переносимым и не зависит от неопределенного поведения.

Возможно, я нашел лучший способ, который переносим и который я считаю«хороший стиль» (если вы не любите присваивание в операторах if).

if(!(obj_ptr = ptr1))
    obj_ptr = ptr2;

Ответы [ 3 ]

10 голосов
/ 10 сентября 2011

Нет, для этого устанавливается obj_ptr на 1, если либо ptr1 не равно NULL, либо ptr2 не равно NULL, а 0 в противном случае.Вам нужно использовать троичный оператор:

obj_ptr = ptr1 ? ptr1 : ptr2;
7 голосов
/ 10 сентября 2011

Ну, это определенно было бы недопустимо в C ++ (где оба операнда повышены до bool).Я признаю, что не уверен насчет C.

[Обновить] OK, нашел его, раздел спецификации C99 6.5.14:

Семантика

||оператор должен выдавать 1, если один из его операндов сравнивается с 0;в противном случае он возвращает 0. Результат имеет тип int.

Поэтому || всегда оценивается либо в 0, либо в 1.

Обычный способ сформулировать это выражение:

obj_ptr = (ptr1 ? ptr1 : ptr2);

Если вам действительно нужен (obj *) актерский состав, есть большая вероятность, что вы делаете что-то не так.

0 голосов
/ 10 сентября 2011

если вам не нравится писать ptr1 дважды, вы можете использовать макрос:

#define or(a, b) (a ? a : b)

obj_ptr = or(ptr1, prt2);
...