2012-03-17 202 views
0

我试图实现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 
~ $ 
+0

'FatalError'是一个'void()'?所以你打电话像'条件? 1:void();'我很惊讶,甚至编译。 – 2012-03-17 10:50:02

+0

源代码。 – blueshift 2012-03-17 10:51:20

+0

这就是逗号运算符的意思,条件变为0(但它并不是因为'FatalError'中的'exit') – rivfaader 2012-03-17 10:54:01

回答

0

显然有一个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

1

好吧,看来,这个问题是Erathostenes功能

if(! GetBit(pole, m)) 

!宏观当然扩大为,

!(range check) ? op1 : op2 

这样的条件被否定

我删除了感叹号和开机先看看op1

((shift, and) ? 0 : 1) 

返回操作数这些值似乎有点不合逻辑,但工作很好

t向大家推荐你的时间