C 宏语法引起的错误

C 宏语法引起的错误,c,macros,C,Macros,我看到了下面的代码,其中一小部分没有意义,因为这超出了我目前的知识范围,我想知道是否有人能帮我解决这个小问题 stack.h #ifndef _STACK_H #define _STACK_H #include "lis1.h" typedef List Stack ; #define stack_init list_init #define stack_destroy list_destroy #define stack_size(stack) (stack)->size #def

我看到了下面的代码,其中一小部分没有意义,因为这超出了我目前的知识范围,我想知道是否有人能帮我解决这个小问题

stack.h

#ifndef _STACK_H
#define _STACK_H

#include "lis1.h"

typedef List Stack ;
#define stack_init list_init
#define  stack_destroy list_destroy
#define stack_size(stack) (stack)->size
#define stack_is_empty(stack) ((stack)->size==0)?1:0

int stack_push(Stack*stack,void*data);
int stack_pop(Stack*stack,void**data); 

#endif
请注意
#define stack_是空的(stack)((stack)->size==0)?1:0
在编写以下程序时

#include<stdio.h>
#include"stack.h"

static char ams[5] = { 'h', 'e', 'l', 'l', 'o' };
void* data;
Stack stack;
char*ss;

void debug(int a)
{
    printf(" debug %d \n", a);
}

int main()
{
    stack_init(&stack, NULL);
    debug(1);
    int i;

    for (i = 0; i < 5; i++)
    {
        stack_push(&stack, (void*) (&ams[i]));
    };
    debug(2);
    while (printf("checker\n") && stack_is_empty(&stack) != 1)
    {
        printf("->");
        printf("[%d  ", stack_size(&stack));
        stack_pop(&stack, &data);
        printf("%c]", *((char*) data));
        printf("--\n");
    };
    return 0;
}
但是如果我改变
#define stack#u是空的(stack)((stack)->size==0)?1:0
若要定义堆栈为空(堆栈)((堆栈)->大小==0)?1:0),则不存在seg故障

我的查询


我的问题是,为什么程序在前一种情况下工作得很好,直到条件输出一个“1”……我似乎理解了为什么后者在宏替换之后工作。

printf("checker\n")&&stack_is_empty(&stack)!=1
变成

printf("checker\n")&&((&stack)->size==0)?1:0!=1
由于三元运算符
?:
的优先级相当低,因此相当于:

(printf("checker\n") && ((&stack)->size==0)) ? 1: (0 != 1)
请注意,
printf(“checker\n”)
始终返回一个真值(因为它返回打印的字符数),因此由于存在快捷电路,因此不会计算check
(&stack)->size==0)


建议:在宏定义中始终使用足够的括号。

在宏替换之后

printf("checker\n")&&stack_is_empty(&stack)!=1
变成

printf("checker\n")&&((&stack)->size==0)?1:0!=1
由于三元运算符
?:
的优先级相当低,因此相当于:

(printf("checker\n") && ((&stack)->size==0)) ? 1: (0 != 1)
请注意,
printf(“checker\n”)
始终返回一个真值(因为它返回打印的字符数),因此由于存在快捷电路,因此不会计算check
(&stack)->size==0)


建议:在宏定义中始终使用足够的括号。

在C语言中,宏只是被文本替换,而不管它是否产生了您可能期望的表达式

如果没有括号,则
while
循环条件扩展为:

printf("checker\n")&&((&stack)->size==0)?1:0!=1
这被解释为:

(printf("checker\n") && ((&stack)->size==0)) ? 1 : (0 != 1)
因此,
printf
成为这个三元表达式的条件的一部分,但这不会引起问题,它返回打印的字节数,只要它不是零,就会被解释为真。然后,根据实际情况,对检查堆栈大小的部件执行and。如果堆栈大小等于零,则返回1或true。如果堆栈大小不等于零,则返回
(0!=1)
的结果,该结果始终为真。因此,这个条件总是返回一个真值,while循环继续运行,即使在堆栈上的项用完之后也是如此

添加括号时,会按预期进行解释:

printf("checker\n") && ((((&stack)->size==0)) ? 1 : 0) != 1)
编写扩展为表达式的宏时,应始终在结果周围加上一对括号,以确保将其解释为单个表达式,而不是可能导致表达式的解释与预期不同的运算符优先级规则

我应该注意到,这一发言中有许多重复之处。您正在检查布尔表达式的值,
(&stack)->size==0
,以查看它是否为真,如果为真,则返回1,如果不是,则返回0。但是
=
已经返回了一个1,如果它是真的,那么返回了一个0;不需要三元运算符。然后使用
!=1
查看它是否为假。但是如何从布尔表达式中得到false呢?只需使用not运算符,
。您可以跳过三元运算符和
!=1
比较:

#define stack_is_empty(stack) ((stack)->size==0)

while (!stack_is_empty(&stack)) {
    // ...
}

在C语言中,宏只是被文本替换,而不管它是否产生了您可能期望的表达式

如果没有括号,则
while
循环条件扩展为:

printf("checker\n")&&((&stack)->size==0)?1:0!=1
这被解释为:

(printf("checker\n") && ((&stack)->size==0)) ? 1 : (0 != 1)
因此,
printf
成为这个三元表达式的条件的一部分,但这不会引起问题,它返回打印的字节数,只要它不是零,就会被解释为真。然后,根据实际情况,对检查堆栈大小的部件执行and。如果堆栈大小等于零,则返回1或true。如果堆栈大小不等于零,则返回
(0!=1)
的结果,该结果始终为真。因此,这个条件总是返回一个真值,while循环继续运行,即使在堆栈上的项用完之后也是如此

添加括号时,会按预期进行解释:

printf("checker\n") && ((((&stack)->size==0)) ? 1 : 0) != 1)
编写扩展为表达式的宏时,应始终在结果周围加上一对括号,以确保将其解释为单个表达式,而不是可能导致表达式的解释与预期不同的运算符优先级规则

我应该注意到,这一发言中有许多重复之处。您正在检查布尔表达式的值,
(&stack)->size==0
,以查看它是否为真,如果为真,则返回1,如果不是,则返回0。但是
=
已经返回了一个1,如果它是真的,那么返回了一个0;不需要三元运算符。然后使用
!=1
查看它是否为假。但是如何从布尔表达式中得到false呢?只需使用not运算符,
。您可以跳过三元运算符和
!=1
比较:

#define stack_is_empty(stack) ((stack)->size==0)

while (!stack_is_empty(&stack)) {
    // ...
}

请记住,C宏只是文本替换,而不是表达式求值

如果使用本影键控堆栈为空,则条件变为:

While (printf("checker\n") && ((&stack)->size)==0)?1:0!=1) {
While (printf("checker\n") && ((&stack)->size)==0)?1:  (0!=1)  ) {
问题是运算符具有高优先级,因此它实际上成为:

While (printf("checker\n") && ((&stack)->size)==0)?1:0!=1) {
While (printf("checker\n") && ((&stack)->size)==0)?1:  (0!=1)  ) {

从0开始1,while循环将继续超出堆栈的大小。

请记住,C宏只是文本替换,而不是表达式求值

如果使用本影键控堆栈为空,则条件变为:

While (printf("checker\n") && ((&stack)->size)==0)?1:0!=1) {
While (printf("checker\n") && ((&stack)->size)==0)?1:  (0!=1)  ) {
问题是运算符具有高优先级,因此它实际上成为:

While (printf("checker\n") && ((&stack)->size)==0)?1:0!=1) {
While (printf("checker\n") && ((&stack)->size)==0)?1:  (0!=1)  ) {
从0开始1,while循环将继续超出堆栈的大小