#运算符和##运算符
这里提前补充一点printf
C语言里面会天然的吧printf里面俩字符串合并为一个
#的使用
在C语言中,`#`符号主要用于预处理器指令。预处理器是在代码编译之前执行的,它处理所有以`#`开始的指令。以下是一些常见的使用情况:
1. **包含头文件**:
使用`#include`指令来包含其他头文件。
```c
#include <stdio.h>
#include "myheader.h"
```
2. **定义宏**:
使用`#define`指令来定义宏,这可以在程序中替换为其他文本。
```c
#define PI 3.14159
printf("The value of PI is: %f\n", PI);
```
3. **条件编译**:
使用`#ifdef`、`#ifndef`、`#if`、`#else`、`#elif`、`#endif`等指令来进行条件编译。
```c
#ifdef DEBUG
printf("Debugging information\n");
#endif
```
4. **行号控制**
:使用`#line`指令来改变编译器输出的行号。
```c
#line 100 "newfilename.c"
// 这行代码的行号将被报告为100,且来源文件被报告为newfilename.c
```
5. **文件包含 guard**:
使用`#ifndef`和`#define`来防止头文件被多次包含。
```c
#ifndef MY_HEADER_H
#define MY_HEADER_H
// 头文件内容
#endif // MY_HEADER_H
```
6. **整型大小指定**:
在C99标准之前,使用`#`后跟整数来指定整型的大小。
```c
#define SHORT int
#define LONG long
```
7. **编译器指令**:
使用`#`来给编译器提供额外的指令,如`#pragma`。
```c
#pragma once
```
请注意,C语言的预处理器不执行任何编程逻辑,它只是简单地替换预处理器指令中的文本。预处理器指令必须在源代码文件中以`//`或`/* */`注释掉之前执行。
具体举例
这里需要知道的是,“format”负责接收类型,这里用双引号,表示占位
也就是,如果你打印的是整数,这里双引号,输入你定义的类型,则此时后面打印的函数会变成你所定义的类型
所以我们可以做到,定义一个宏之后,我们可以使用多个模版进行套用,减少代码的冗余性。
这里我想不只是n,那我用#+变量
#
在宏定义中是一个操作符,用于连接字符串和宏参数。它并不是双引号的一部分。双引号用于定义宏中的字符串字面量,如 "数值的计算"
。
结果是一样的,但是字符发生了变化
#n
是在宏定义中使用双引号包围的字符串字面量的一部分,它会在宏展开时被替换为 n
的值。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#define M(n,format) printf("数值的计算"#n ":is="format"\n",n)
int main()
{
int a = 1;
M(a, "%d");
long long b = 10;
M(b, "%d");
double c = 0.1;
M(c, "%lf");
return 0;
}
#define M(n,format) printf("数值的计算"#n ":is="format"\n",n)
这个宏 `M` 定义了一个带两个参数的宏:`n` 和 `format`。当这个宏被调用时,它会展开为以下代码:
printf("数值的计算"#n ":is="format"\n",n)
其中 `#n` 会被替换为 `n` 的实际值,`format` 会被替换为实际的格式字符串。例如,如果 `M(a, "%d")` 被调用,
那么它会展开为:printf("数值的计算1:is=%d\n",a)
这里的 `"数值的计算1:is=%d\n"` 是一个字符串字面量,其中 `%d` 是一个格式占位符,用于在运行时由 `a` 的值替换。
所以这里我们得到的答案也就是我们预期的答案
##运算符
可以把位于两端的符号合成一个符号 这里就是链接max,
简单说就是我们可以定义类型,如果type传过来的是int类型,那么我们就可以把所有的type换成int,此时会发发现,这个宏有了类型之分。但是我们计算的变量的名字我们希望是独一无二的,此时我们可以用##链接类型,也就是变成了
type type__max(int x,int y);这个就变成了宏的定义
可以进行一个两个数值的比较大小,并且只需要进行定义一个类型就哭哭完成相应的计算。
怎么使用的 就等于
我们在gcc里面进行观察
批量创造相似的函数
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#define COMPUTE(type) \
type type##_COMPUTE(type x,type y)\
{\
return x>y?x:y;\
}
//函数的定义
COMPUTE(int);//int_COMPUTE
COMPUTE(float);//float_COMPUTE
int main()
{
int ret1 = int_COMPUTE(3, 5);
printf("%d\n", ret1);
float ret2 = float_COMPUTE(3.1f, 4.5f);
printf("%f\n", ret2);
return 0;
}
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
命名约定
⼀般来讲函数的宏的使⽤语法很相似。所以语⾔本⾝没法帮我们区分⼆者。
那我们平时的⼀个习惯是:
把宏名全部⼤写
函数名不要全部⼤写
#undef
这条指令⽤于移除⼀个宏定义。
#undef NAME
//如果现存的⼀个名字需要被重新定义,那么它的旧名字⾸先要被移除。