三元运算符作为C宏中三元运算符的操作数
问题描述:
我试图实现Erathostenes的筛子来获得unsigned long
数组的一个主要位,所以我写了一个宏来检查某个位的值。(函数会更容易但它是学校排序,所以它必须是宏)我需要测试索引是否在位的范围内,所以有函数调用FatalError
,这是void函数与调用exit(1)
,所以逗号运算符使整个宏可能是条件的内部三元运算符作为C宏中三元运算符的操作数
#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
~ $
答
显然有一个bug,所以忽略了“正确“的答案形式,并且让自己很容易找到错误。如果你走一条更简单的路线,它可能会更快地发现问题。只要你试图坚持一个宏,它可能会更难调试。
具体而言,我会将宏变成一个函数,使其更易于调试,然后将表达式分解为组件部分,并添加一些打印语句以更好地理解正在发生的事情:
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]);
+0
我刚刚找到了正确的答案,但我还应该告诉? – 2012-03-17 11:22:09
答
好吧,看来,这个问题是Erathostenes功能
if(! GetBit(pole, m))
与!
宏观当然扩大为,
!(range check) ? op1 : op2
这样的条件被否定
我删除了感叹号和开机先看看op1
((shift, and) ? 0 : 1)
返回操作数这些值似乎有点不合逻辑,但工作很好
t向大家推荐你的时间
'FatalError'是一个'void()'?所以你打电话像'条件? 1:void();'我很惊讶,甚至编译。 – 2012-03-17 10:50:02
源代码。 – blueshift 2012-03-17 10:51:20
这就是逗号运算符的意思,条件变为0(但它并不是因为'FatalError'中的'exit') – rivfaader 2012-03-17 10:54:01