预处理内容

这章是基于我学的知识进行讲解我今天学的内容,希望大家能够喜欢

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include <ctype.h>
预处理详解2
函数与宏的不同
宏可以执行简单的运算
如:比较两个数,求出两个数中的最大值
宏程序简单,不用调用,速度和规模相对小
 其次,宏的参数没有类型声明,任何两个数都可以比较大小
 宏相对函数的劣势:
 1.如果宏比较长,每次使用宏的时候将大幅度增加程序的长度
 2.宏是无法调试的
 3.宏参数与类型无关,不够严谨
 4.宏可能会带来运算符优先级的问题,程序容易出错
 #和##
 #运算符
 我们知道打印helloworld可以这样打印
 printf("helloworld");
 但是也可以这样打印
printf("hello""world");
 如果我们想在屏幕上打印the value of c is 3
则我们会这样打印
int main()
{
    int a = 3;
    int b = 4;
    int d = 5;
    printf("the value a is %d", a);
    printf("the value b is %d", b);
    printf("the valuw d is %d", d);
    //但是这样打印重复的句子会显得很麻烦
    //不妨用宏定义一下
    return 0;
}
#define print(v,format) printf("the value of "#v" is""%d""\n",v)
int main()
{
    int a = 3;
    int b = 4;
    int d = 5;
    print(a);
    print(b);
    print(d);
    /*结果
    * the value of a is3
      the value of b is4
      the value of d is5
    */
    return 0;
}
##运算符
##可以把位于它两边的符号合成为一个符号
它允许宏定义从分离的文本片段创建一个标识符
##被称为记号粘合,这样的连接必须产生一个合法的标识符,否则结果是未定义的
如:
#define cat(x,y) x##y
int main()
{
    int abc123;
    printf("%d", cat(abc, 123));
    //这样能打印出abc123的值
    //但是如果y是124,则未定义
    //会报错
    return 0;
}
如果我们想写一个比较大小的函数,实现每种类型都能比较,如何写
如果写出四种或者以上类型,很麻烦
不妨用宏试试
#define gr_MAX(type) type type##_MAX(type a,type b)\
{\
return ((a)>(b)? (a):(b))\
}
//当产生函数时输入一个类型即可产生该函数
gr_MAX(int);
这样就会产生一个函数名为
int_MAX的函数
只要之后调用时int_MAX(a,b);
即可
命令行编译
int main()
{
    int arr[sz] = { 0 };
    int i;
    for (i = 0; i < sz; i++)
    {
        arr[i] = i + 1;
    }
    for (i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);
    }
    return 0;
}
上面的sz未定义,会报错
但是如果在gcc这种编译器上在编译时输入
sz=100
即可完成该代码
会在预处理中把sz的值进行替换
#undef
#define m 100
int main()
{
    printf("%d", m);
#undef m
    printf("%d", m);//后面这个语句会报错
    //表示m未定义
    //undef的作用是移除一个宏定义
    return 0;
}
条件编译
#define d
int main()
{
    int arr[10] = { 0 };
    int i = 0;
    for (; i < 10; i++)
    {
        arr[i] = i + 1;
#ifdef d
        printf("%d", arr[i]);
#endif
        //打印数组所有元素的句子我们不一定需要
        //但是又删掉之后无法知道其值
        //我们可以在开始时定义d
        //之后不想打印时在注释掉这个常量表达式即可

    }
    return 0;

 //条件编译的其他符号
 }
#if 常量表达式
#endif
如:
int main()
{
#if 2==3
    printf("hehe\n");
#endif
    return 0;
}
如果加上其他如#define定义的呢
#define m 3
//由于m是在预处理时就开始转变了所以这样是正确的
int main()
{
#if 2==m
    printf("hehe\n");
#endif
    return 0;
}
int main()
{
    int a = 3;
    //错误了,变量在预处理时还没有创建
    //所以会报错
#if a==3
    printf("hehe\n");
#endif
    return 0;
}
int main()
{
#if 2==3
    printf("hehe\n");
#elif 2==2
    printf("haha\n");
#else
    printf("hello\n");
    //可以看到,除了第二句话其他句子颜色都变淡了
    //所以这个语句就会执行
#endif
    return 0;
}
if defined()
endif
#define m 3
int main()
{
#if defined(m)
    printf("hehe\n");
#endif
    //这个是判断括号里面的常量是不是被定义了
    return 0;
}
同样的意思
#ifdef
#define m 3
int main()
{
#ifdef m
    printf("hehe\n");
#endif
    //也可以加个else
    //这个只关心常量是否被定义,而不管他的值
    //所以m没定义也好,定义为0也可,都会执行这句话
    return 0;
}
头文件的包含
头文件被包含的方式
本地文件的包含
用双引号来包含文件名
两种方式的主要区别是查找策略的不同
这种是我们自己创建的文件的主要包含方式
#include "add,h"
先会在该文件寻找是否有这个函数,再进行源函数的查找
库文件的包含
一般用<>来包含函数名
如:
#include <stdio.h>
#include<math.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include <ctype.h>
这些函数包含后就会直接在你这个下载的编译器路径下查找函数
相对于双引号的方式效率更高
如果不小心包含了好几次文件会有什么后果呢
预处理时会把所有该文件的内容全部拷贝到该位置
如果文件的代码长,就会使效率变低
有什么方法呢
一般有两种方法的
1.条件编译
假设这上面是add.h的内容
int Add(int x, int y);
如何修改
#ifndef m
#define m 3
int Add(int x, int y);
#endif
当第一次包含头文件时会直接把那个函数声明拷贝到里面去
但是第二次就会直接忽略了
在这种格式下我们可以直接把#endif和#define之间进行函数的内容书写
这样就不会报错了
还有一种方法
当我们在创建头文件的时候会有这样一句话
#pragma once
当添加进这句话就会只包含一次
所以我们就可以在以后创建文件时这样写
到此C语言所有内容已经学完了
明天就要学习数据结构了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值