所以,我一直在阅读GCC的文献,直到我读到第Statements and Declarations in Expressions节,第6.1,follow this link to reach the section I am talking about节.

我读到了这些奇怪的台词,GCC说

此功能在使宏定义"安全"(以便它们只对每个操作数求值一次)时特别有用.例如,在标准C中,"Maximum"函数通常被定义为宏,如下所示:

#define max(a,b) ((a) > (b) ? (a) : (b))

但该定义计算a或b两次,如果操作数有副作用,则结果不佳.在GNU C中,如果您知道操作数的类型(这里视为int),则可以通过按如下方式定义宏来避免此问题:

#define maxint(a,b) ({int _a = (a), _b = (b); _a > _b ? _a : _b; })

从我的理解来看,GCC建议知道争论的类型,现在我脑子里有很多问题.

  1. 为什么我必须知道参数的类型?我的意思是,C宏就像文本的替代品,所以我认为max(a,b)可以很好地处理任何原始数据类型,无论它是整型、浮点型、双精度型等等.

  2. 我不知道maxint(a,b)将如何工作,我的意思是它是一个奇怪的三元运算符签名,我的意思是例如在下面的代码行中:

    #include <stdio.h>
    
    #define maxint(a,b) \
      ({int _a = (a), _b = (b); _a > _b ? _a : _b; })
    
    int main()
    {
        int x = 5;
        int y = 10;
        int z = maxint(x , y);
        printf("z = %d",z);
    }
    

z value will be 10,这是一个正确的答案,接下来的几行是生成的行 在上述代码的编译器完成预处理之后:

int main()
{
    int x = 5;
    int y = 10;
    int z = ({int _a = (x), _b = (y); _a > _b ? _a : _b; });
    printf("z = %d",z);
    return 0;
}

我的问题是在第int z = ({int _a = (x), _b = (y); _a > _b ? _a : _b; });行,这一行如何计算z为10,我的意思是,它只是一块行,没有返回值.只有在运行时计算为时,我才会看到此行

int z = ({int _a = (5), _b = (10); 10; });个 因为整个三元运算将被值10替换,因为(5 > 10 ? 5 : 10)将被10替换,这对我来说没有意义地将代码块分配给原始数据类型(在我的例子中是z)

  1. 他们在上面引用的几行中说

但是这个定义计算a或b两次.

谈到这个宏max(a,b),我不明白这个宏是如何计算a或b两次的,以及宏maxint(a,b)是如何解决这个问题的?

推荐答案

为什么我必须知道参数的类型?

计算once个自变量,在作业(job)中.

(如果你没有,你可以使用另一个GCC分机__auto_type__typeof__.)

我是说,这是一个奇怪的三元运算符签名

这是GCC的一个扩展,称为语句表达式https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html.

这只是一段代码,没有返回值

从这份文件中可以看出:The last thing in the compound statement should be an expression followed by a semicolon; the value of this subexpression serves as the value of the entire construct.值_a > _b ? _a : _b;是最后一个,它充当({...})的"返回值".

这个宏如何计算a或b两次,宏Maxint(a,b)如何解决这个问题?

在GCC文档https://gcc.gnu.org/onlinedocs/cpp/Duplication-of-Side-Effects.html#Duplication-of-Side-Effects中的宏观trap 中进行了解释.

许多C程序定义了一个宏MIN,表示"最小值",如下所示:

#define min(X,Y)((X)<;(Y)?(X):(Y))

将此宏与包含副作用的参数一起使用时, 如下所示,

Next=min(x+y,foo(Z));

它的扩展如下:

Next=((x+y)<;(foo(Z))?(x+y):(foo(Z);

C++相关问答推荐

try 使用sigqueue函数将指向 struct 体的指针数据传递到信号处理程序,使用siginfo_t struct 体从一个进程传递到另一个进程

Mise()在虚拟内存中做什么?

通过管道将一个子系统的标准输出发送到另一个子系统的标准输出

标准的C17标准是用括号将参数包装在函数声明中吗

增加getaddrinfo返回的IP地址数量

将常量转换为指针会增加.数据大小增加1000字节

在Apple Silicon上编译x86的Fortran/C程序

为什么函数是按照定义的顺序执行的,而不是按照从avr-c中的int main()调用的顺序执行的?

关于scanf()和空格的问题

当内存来自Malloc时,将char*转换为另一个指针类型是否违反了严格的别名规则?

C堆栈(使用动态数组)realloc内存泄漏问题

在C++中允许使用字符作为宏参数

仅从限制指针参数声明推断非混叠

为什么会导致分段故障?(C语言中的一个程序,统计文件中某个单词的出现次数)

Matlab/Octave对conv2函数使用哪种方法?

如何找出C中分配在堆上的数组的大小?

memcmp 是否保证按顺序比较字节?

System V 消息队列由于某种原因定期重置

如何使用 raylib 显示数组中的图像

无法在 C 中打开文本文件,我想从中读取文本作为数据并将其写入数组