简体   繁体   English

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

[英]Ternary operator as operand of ternary operator in C macro

I'm trying to implement Sieve of Erathostenes to get prime bits of an unsigned long array, so I wrote a macro to check the value of certain bit.. (function would be easier but it's school asignment so it has to be macro) I needed to test whether the index is in range of bits, so there is function call FatalError , which is void function with exit(1) call, so the comma operator makes the whole macro possible to be inside of condition 我正在尝试实现Erathostenes的筛选以获取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)

More readable form: 更具可读性的形式:

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

On array_name[0] , there is the size of the array in bits. array_name[0] ,存在以位为单位的数组大小。

So my problem is, that not even the first index can get through range check, the Sieve starts with index 2 and the program immediately ends with 所以我的问题是,即使第一个索引也无法通过范围检查,筛号以索引2开头,程序立即以结束

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

Well, it seems, that the problem was in Erathostenes function in 好吧,看来问题出在Erathostenes函数中

if( ! GetBit(pole, m) )

with the ! ! macro of course expanded as, 宏当然会扩展为

!(range check) ? op1 : op2

so the condition was negated 所以病情被否定了

I removed the exclamation mark and switched the return operands of op1 我删除了感叹号,并切换了op1的返回操作数

((shift, and) ? 0 : 1)

on first look the values seem a little illogical, but work just fine 乍一看,这些值似乎有些不合逻辑,但工作正常

thanks to everyone for your time 感谢大家的时间

Clearly there is a bug, so ignore the 'correct' form of answer, and make it easy for yourself to find the bug. 显然有一个错误,因此请忽略“正确”形式的答案,并让自己轻松找到错误。 It'll likely be quicker to find the problem if you go an easier route. 如果走更简单的路线,发现问题可能会更快。 As long as you try to stick with a single macro, it is likely to be harder to debug. 只要您尝试使用单个宏,就可能很难调试。

Concretely, I'd turn the macro into a function, to make it easier to debug, then break the expression down into component parts, and add a load of print statements to get a better understanding of what is happening: 具体来说,我会将宏转换为函数,以使其易于调试,然后将表达式分解为组成部分,并添加大量打印语句,以更好地了解正在发生的事情:

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.

and redefine getbit to use 并重新定义要使用的getbit

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM