2009-12-02 3 views
1
while (curr_data[1] != (unsigned int)NULL && 
    ((curr_ptr = (void*)curr_data[1]) || 1)) 

Вопрос из двух частей.Логическое значение задания в C

Что будет (curr_ptr = (void*)curr_data[1]) оценить, логически. TRUE?

Кроме того, я знаю его довольно хак-иш, но является ли заявление while законным? Мне пришлось бы пройти через большие искажения, чтобы поставить задание в другом месте кода, поэтому я был бы очень хорош, если бы мог оставить его там, но если это так вопиющее, что он заставляет все глаза зарыться в пламя, я его изменю ,

+0

Я думаю, вы должны отправить на «The Daily WTF». – 2009-12-02 08:43:33

+1

есть сердце для бедной души, которому придется прочесть эти строки, может быть, вы тоже через 6 месяцев – Alon

+2

Ummm ... истекающие кровью глаза. Да, конечно, кровоточащие глаза. –

ответ

2

чтобы ответить на ваши вопросы:

  1. Он оценит истинно, если curr_ptr не установлен в NULL (т.е. curr_data[1] не 0).
  2. Я считаю, что это законно, но с этой строкой кода возникают большие проблемы.

В любом случае, я предполагаю, что вы не пишете этот код, потому что вы обсуждаете его отказ от его снятия. Поэтому я хочу, чтобы вы узнали, кто написал эту строку кода и познакомил их с тяжелым тупым объектом.

  1. (unsigned int)NULL нелепо. Зачем вам это делать? Вероятно, это будет то же самое, что просто написать 0 (не уверен, что это гарантировано стандартом).
  2. Какие данные находятся в curr_data[1], если он бросается в указатель (и указатели на него набрасываются)? Если предполагается, что указатель является целым типом, вы должны использовать тип intptr_t или uintptr_t, указанный в <stdint.h> для этой цели (если вы не поддерживаете C99 ptrdiff_t, может быть приемлемой заменой).
  3. || 1 в конце кажется излишним. Если бы curr_ptr = (void*)curr_data[1] оценил значение false, мы бы поймали это в первом условии.

Это может быть боль в попке, но серьезно пересмотреть переписывание этой линии. Это похоже на запись в IOCCC.

+0

Ха-ха, тяжелые тупые предметы были применены к этому человеку уже в форме удара из двери. В любом случае ... 1. литье 'NULL' как' unsigned int' предотвращает предупреждение 'warning: присваивание делает целое число из указателя без cast'. Я просто оставил его, чтобы избежать повторного набора половины программы. 2. Хорошая идея. Я посмотрю, смогу ли я сделать это изменение, не нарушая слишком многого. 3. Да, мне было интересно об этом, особенно в свете первого ответа, который я получил. –

+0

Если вам нужно сделать бросок, нарисуйте 'curr_data [1]' на тип указателя, чтобы лучше отразить, как вы собираетесь его использовать. Однако, если он удерживает 0, приведение его к указателю даст «NULL», поэтому вы можете так же легко выполнить 'curr_data [1]! = 0' или даже' curr_data [1] 'и иметь такую ​​же логическую проверку. Мое личное, надеюсь, более читаемое переписывание: 'while (curr_data [1]) curr_ptr = (void *) curr_data [1];' –

+0

И версия, которая работает, зная это, является частью цикла 'do {} while': do {...} while (curr_ptr = (void *) curr_data [1]); «В качестве альтернативы, если вам нужно иметь не-trash' curr_ptr' после завершения цикла: 'do {...} while (curr_data [1] && curr_ptr = (void *) curr_data [1]); 'Надеюсь, это должно сработать. –

3

(curr_ptr = (void*)curr_data[1]) будет оценивать значение TRUE, если он не является нулевым указателем.

Предполагая, что curr_data представляет собой массив указателей, и то, что вы хотите сделать, это запустить цикл в то время как второй из этих указателей не равно нулю, при назначении его значение curr_ptr, я хотел бы сделать:

while ((curr_ptr = (void*)curr_data[1]) != NULL) { ... } 
+1

О, так моя первоначальная проверка избыточна, то? Моя первоначальная проверка заключается в том, чтобы увидеть, содержит ли 'curr_data [1]' значение null, но вы говорите, что это будет делать то же самое? –

+2

Нет, потому что если исходная проверка завершилась неудачей, назначение никогда не произойдет ('&&' имеет «семантику» раньше), а цикл while будет завершен. В то время как '|| 1 будет делать цикл while продолжительным, если вы удалите начальную проверку. '|| 1 бит - это лишний. – caf

1

Назначения - это выражения в C, поэтому у вас есть работы. Изменение ; на {} означает то же самое и намного яснее, сделайте это, по крайней мере. Задания в условиях следует избегать, если у вас есть более ясная альтернатива (как правило, это правда), но если это яснее в этом месте, используйте ее.

Результатом присвоения является назначенный объект. a = value выполнит задание, а затем оценит его до a. Это используется, чтобы сделать что-то вроде a = b = 0.

Для дальнейшей очистки кода нет необходимости в листинге void, и если это символы, используйте '\ 0' (нулевой символ) вместо NULL (который должен использоваться только с указателями).

0

Вам не придется пройти через «великие судороги», что полностью соответствует

while (curr_data[1]) { 
    curr_ptr = (void *)curr_data[1]; 
+0

К сожалению, это часть цикла do-while. –

+0

@ Энди - Аааааа! Здесь мы сталкиваемся с реальной проблемой. Мне было интересно, почему мы зациклились до конца, не делая никакой работы. –