我在学习C语言中的函数和类似函数的宏.

我读了C标准,发现了这个:

函数的任何宏定义都可以通过将函数的名称括在圆括号中来局部取消,因为该名称后面没有表示宏函数名展开的左括号.出于相同的语法原因,允许使用库函数的地址,即使它也被定义为宏.185)使用#undef删除任何宏定义也将确保引用实际的函数.

因此,根据这一点,如果我想确保GET将是我代码中的一个函数,我必须访问<stdio.h>头文件,并将(我不知道是函数名还是宏名)括在括号或#undef宏中?

我的意思是:int (getc)(FILE *stream);(或者这个?#define (getc)(...) ) 或者这样: 一百零二

但这一切都在<stdio.h>档案?

还是在我的代码里?

你能给我一个例子,说明如何确保在C中使用getc作为函数吗?

推荐答案

正如引用的段落中所解释的,有一种简单的方法可以防止标准库头中定义的类似函数的宏的宏扩展:使用后面不跟(的标识符来引入参数列表,例如:在标识符两边使用括号.

例如:

#include <stdio.h>

// copy stdin to stdout bypassing macro expansion
int main(void) {
    int c;
    while ((c = (getc)(stdin)) != EOF) {
        (putc)(c, stdout);
    }
    return 0;
}

或者,您可以在使用代码中的函数之前取消定义宏.这将确保预处理器保持getcputc标识符不变,并且编译器将使用它们在<stdio.h>中的函数声明.

#include <stdio.h>

// copy stdin to stdout preventing macro expansion

#undef getc
#undef putc
#undef fgetc
#undef fputc

int main(void) {
    int c;
    while ((c = getc(stdin)) != EOF) {
        putc(c, stdout);
    }
    return 0;
}

一种更简单的方法是使用函数fgetcfputc,即使它们也可以被实现为用于性能的宏,它们也被保证表现为函数:

#include <stdio.h>

// copy stdin to stdout using the functions
int main(void) {
    int c;
    while ((c = fgetc(stdin)) != EOF) {
        fputc(c, stdout);
    }
    return 0;
}

在任何情况下,都不要try 修改标准标头,因为在现代系统上,标头应该是只读的.

另请注意,在<stdio.h>中定义的标准函数的宏版本只允许对流参数(对应于FILE *的参数)进行多次求值,而不允许对字符参数进行多重求值.不能保证这一点的古代系统不符合任何C标准,并且完全过时.例如,参见ISO C90文件中putc函数的规范:

7.9.7.8 100 function

Synopsis

#include <stdio.h>
int putc(int c, FILE *stream);

Description

putc函数等同于fputc,不同之处在于,如果它作为宏实现,它可能会多次计算stream,因此参数永远不应该是有副作用的表达式.

最后一句话是:不要担心这一点,毫不犹豫地使用宏或函数,但不要将有副作用的表达式作为流参数传递,这无论如何都会非常麻烦和容易出错.

C++相关问答推荐

Can函数指针指向C++中具有不同参数连续性的函数

双指针指向常量双指针的指针类型赋值不兼容

在基本OpenGL纹理四边形中的一个三角形中进行渲染

GDB输出ARM助记符

Vcpkg的配置文件

无法在OpenGL上绘制三角形

这段代码用于在C中以相反的顺序打印数组,但它不起作用

有没有一种方法可以用C创建保留限定符的函数?

C-try 将整数和 struct 数组存储到二进制文件中

将复合文字数组用作临时字符串缓冲区是否合理?

浮点正零何时不全为零?

为什么argc和argv即使在主函数之外也能工作?

使用替代日历打印日期

添加/删除链表中的第一个元素

变量的指针右对齐,函数的指针左对齐

C 中从 Unix 纪元时间转换的损坏

C99 的 %zu 格式说明符不起作用

用C程序读取.txt文件并解析,如何处理空字段

编程时什么时候使用原子操作?

从 struct 中的函数指针访问数据成员