C语言学习记录——오십팔 C语言预处理(2)

目录

预处理(预编译)详解

预定义符号

#define

#define 定义宏

#define替换规则

#和##


预处理(预编译)详解

预定义符号

__FILE__ 这个代码所在的这个文件的名称

__LINE__ 文件当前的行号

__DATE__ 文件被编译的日期

__TIME__ 文件被编译的时间

__STDC__ 如果编译器遵循ANSCII,其值为1,否则未定义

可以利用这个写日志文件

#include <stdio.h>

int main()
{
    int i = 0;
    int arr[10] = { 0 };
    FILE* pf = fopen("log.txt", "w");
    for (i = 0; i < 10; i++)
    {
        arr[i] = i;
        fprintf(pf, "file:%s line:%d date:%s time:%s i=%d\n",
            __FILE__, __LINE__, __DATE__, __TIME__, i);
    }
    fclose(pf);
    pf = NULL;
    for (i = 0; i < 10; i++)
    {
        printf("%d ", arr[i]);
    }
    return 0;
}

也可以打印函数名字

        arr[i] = i;
        fprintf(pf, "file:%s line:%d date:%s time:%s i=%d\n",
            __FILE__, __LINE__, __DATE__, __TIME__, i);
        printf("%s\n", __FUNCTION__);

这样就能打印出main。

__STDC__需要遵循ANSCII才可以使用

#define

是一种预处理指令。井号开头的都是预处理指令

#define  name   stuff(内容) 这里也就展现出自由性高

#define do_forever for(;;)

int main()
{
    do_forever;
    return 0;
}

这样也就死循环了。如果forever后面没有; 也就是do_forever    return 0;  那么就不会死循环,执行完for语句后,就会return 0,程序结束。

#define MAX 100后面不能加分号,比如

#include <stdio.h>

#define MAX 100

int main()
{
    int a = MAX;
    printf("%d\n", 100);
    return 0;
}

MAX后面的都是内容,所以如果是100;  那么MAX就会在main函数体内被传换成100;  容易出问题。

#define 定义宏

#define机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏或定义宏。

宏的申明方式:

#define name(parament-list)  stuff 其中的parament-list是一个由逗号隔开的符号表,它们可能出现在stuff中。参数列表的左括号必须与name紧邻, 如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分。

#include <stdio.h>

#define SQUARE(X) X*X

int main()
{
    int ret = SQUARE(5);
    printf("%d\n", ret);
    return 0;
}

这样ret就是25.SQUARE就是宏。但是这样的定义有问题

#define SQUARE(X) X*X

int main()
{
    int ret = SQUARE(5 + 1);
    printf("%d\n", ret);
    return 0;
}

如果这样的代码,结果是11。宏的实现是替换而来的,x会被替换为5+1,那么这个计算就是5+1*5+1,也就是11。如果想打印36,那么把X变成(X)就好,#define SQUARE(X) (X)*(X),因为*的优先级比+高。

#define DOUBLE(X) X+X

int main()
{
    int a = 5;
    int ret = 10 * DOUBLE(a);
    printf("%d\n", ret);
    return 0;
}

这样仍然是替换,10*5+5,所以是55。

#define替换规则

在程序中扩展#define定义符号和宏时,需要涉及几个步骤。

1、在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先被替换

#define MAX 5
#define DOUBLE(X) ((X)+(X))   

int ret = 10 * DOUBLE(MAX);

那就先把MAX替换完

2、替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值替换。

3、最后,再次对结果文件进行扫描,看看它是否报刊任何由#define定义的符号。如果是,就重复上述处理过程。

注意:

1、宏参数和#define定义中可以出现其他#define定义的变量。但是对于宏,不能出现递归

2、当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。

printf("MAX = %d\n", MAX);  像这样,只有单独的那个MAX会被替换。

#和##

int main()
{
    int a = 10;
    printf("the value of a is %d\n", a);
    return 0;
}

把这个printf换成一个函数

void print(int a)
{
    printf("the value of a is %d\n", a);
}

int main()
{
    int a = 10;
    print(a);
    return 0;
}

还是一样的结果,现在添加另一个变量

void print(int a)
{
    printf("the value of a is %d\n", a);
}

int main()
{
    int a = 10;
    int b = 20;
    print(a);
    print(b);
    return 0;
}

但是这样就会变成the value of a is 20;如果想the value of b is 20。如果想传b还是a都能成输出正确的内容,可以用宏,用宏前先写一个东西

int main()
{
    printf("hello world\n");
    printf("hello" "world\n");
    printf("hel" "lo" "world\n");
}


无论怎样拆分,都会打印一样的内容,两三个字符串都会拼在一起打印。再看宏

#define PRINT(X) printf("the value of X is %d\n", X)

int main()
{
    int a = 10;
    int b = 20;
    PRINT(a);
    PRINT(b);
    return 0;
}

这样还是会错误,会一直打印有X

#define PRINT(X) printf("the value of "#X" is %d\n", X)

X左右的两个引号,使the value of 和is %d变成两个字符串,而#X也是变成了字符串

使用#,把一个宏参数变成对应的字符串

##可以把位于它两边的符号合成一个符号。它允许宏定义从分离的文本片段创建标识符

#define CAT(X, Y) X##Y

int main()
{
    int a3 = 47;
    printf("%d\n", CAT(a, 3));
    return 0;
}

这样就是连起来变成a3,也就打印出来47。代码在预处理后,就会直接变成a3。

结束。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值