Тернарный оператор как операнд тернарного оператора в макросе C - PullRequest
1 голос
/ 17 марта 2012

Я пытаюсь реализовать Sieve of Erathostenes для получения простых битов массива unsigned long, поэтому я написал макрос для проверки значения определенного бита .. (функция была бы проще, но это школьное присвоение, поэтому она должна быть макросом) Мне нужно было проверить, находится ли индекс в диапазоне битов, поэтому есть вызов функции FatalError, которая является функцией void с вызовом exit(1), поэтому оператор запятой делает возможным весь макрос находиться внутри условия

#define GetBit(array_name, index) \
  (((index) < (array_name)[0]) && ((index) >= 0)) ? \
  (((array_name)[((index) / BYTE) + 1] & ( (unsigned long)1 << \
    ((index) % BYTE))) ? 1 : 0) : \
  (FatalError("Index %ld out of range 0..%ld\n", (long)(index), \
    (long)(array_name)[0]), 0)

Более читабельная форма:

#define GetBit(array_name, index) \
  (range check) ? \
  ((bit shift, and) ? 1 : 0) : \
  (function call, 0)

На array_name[0] указан размер массива в битах.

Так что моя проблема в том, что даже первый индекс не может пройти проверку диапазона, сито начинается с индекса 2, а программа немедленно заканчивается

~ $ gcc primes.c fatalerror.c -pedantic -Wall -g -std=c99 -lm; ./a.out
FATAL ERROR: Index 2 out of range 0..1000
~ $ 

Ответы [ 2 ]

1 голос
/ 18 марта 2012

Что ж, похоже, проблема была в функции Erathostenes в

if( ! GetBit(pole, m) )

с макросом !, конечно, расширенным как

!(range check) ? op1 : op2

, поэтому условие было отменено

Я удалил восклицательный знак и переключил операнды возврата op1

((shift, and) ? 0 : 1)

на первый взгляд значения кажутся немного нелогичными, но работают просто отлично

спасибовсем за ваше время

0 голосов
/ 17 марта 2012

Очевидно, что есть ошибка, поэтому игнорируйте «правильную» форму ответа и упростите ее поиск. Вероятно, будет быстрее найти проблему, если вы пойдете по более легкому пути. Пока вы пытаетесь придерживаться одного макроса, его, вероятно, будет труднее отлаживать.

Конкретно, я бы превратил макрос в функцию, чтобы упростить отладку, затем разбил бы выражение на составные части и добавил множество операторов печати, чтобы лучше понять, что происходит: *

printf("(((index) < (array_name)[0]) && ((index) >= 0)) = %d\n", 
        (((index) < (array_name)[0]) && ((index) >= 0)));
printf("(array_name)[((index) / BYTE) + 1] = %d\n", 
        (array_name)[((index) / BYTE) + 1]);
printf("( (unsigned long)1 << ((index) % BYTE)) = %d\n", 
        ( (unsigned long)1 << ((index) % BYTE)));
printf("BYTE=%d\n", BYTE);

// etc.

и переопределите getbit для использования

printf("Index %ld out of range 0..%ld\n", (long)(index), (long)(array_name)[0]);
...