三元运算符作为C宏中三元运算符的操作数

时间:2012-03-17 10:38:53

标签: c macros ternary-operator

我正在尝试实现Erathostenes的Sieve来获取unsigned long数组的主要部分,所以我写了一个宏来检查某些位的值..(函数会更容易,但它是学校的校准,所以它必须是宏)我需要测试索引是否在位范围内,所以有函数调用FatalError,这是带有exit(1)调用的void函数,所以逗号运算符使整个宏成为可能处于条件之内

#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]上,数组的大小为位。

所以我的问题是,即使是第一个索引也不能通过范围检查,Sieve从索引2开始,程序立即以

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

2 个答案:

答案 0 :(得分:1)

好吧,似乎问题出现在Erathostenes函数

if( ! GetBit(pole, m) )

当前!宏已扩展为

!(range check) ? op1 : op2

所以条件被否定了

我删除了感叹号并切换了op1

的返回操作数
((shift, and) ? 0 : 1)

首先看看价值看起来有点不合逻辑,但工作得很好

感谢大家的时间

答案 1 :(得分:0)

显然存在一个错误,因此请忽略“正确”的答案形式,并让自己轻松找到错误。如果你走得更方便,找到问题可能会更快。只要您尝试使用单个宏,就可能更难调试。

具体来说,我将宏转换为函数,使其更容易调试,然后将表达式分解为组件部分,并添加一组print语句以更好地理解正在发生的事情:

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]);