//#define 宏定义(宏定义一般大写)
//知识点一-->#define的作用域:从#define开始,从上往下,如果遇到#undef就到#undef处结束,如果没有就是作用于当前整个文件


#include<stdio.h>
#include<stdlib.h>
//知识点二-->宏定义作用
//宏定义作用1:起到替换作用,可以定义常量
#define X 10

//宏定义作用2:替换代码的任意部分(一般用于易语言,或者加密代码)
#define 水乃万物之源 main

//注意:宏定义不是普通C 语句,在行末不必加分号,如加上分号则连分号也一起置换
#define Y 100;

//知识点三-->带参数的宏定义(可以部分替代函数调用)
//①带参数的宏仅仅是替换,不求出实际参数的值,函数调用时,会计算参数的值
//②函数调用时会给参数分配内存,宏仅仅是替换,不占用内存
//③函数有返回值的概念,宏没有返回值的概念,返回的是一个表达式,表达式的结果等价于函数的返回值
//④函数调用时是有类型的,宏替换不需要类型
//⑤宏替换展开时代码变长,函数调用不会

//函数调用时跳转,返回耗费时间,占用资源

//多个函数调用会让程序运行时间增加,不影响预处理时间
//多个宏调用,会让预处理时间增加,运行时间会短


#define FL(x) x*x 


//求两个数的最小数
#define MYMIN(x,y) x>y?y:x

#define MYTEX(x,y) x*y
#define MYTEX2(x,y) (x)*(y)

//#define MYTEX2((x),(y)) (x)*(y) 这样的宏定义是错误的,带参数的宏的参数上不可以有()

//知识点四-->宏定义语句中#的作用是将参数变成字符串
#define MYTEF(x) printf("%s\n",#x)
#define MYTEF2(x) printf("%s---%d\n",#x,x)

//知识点五-->在C语言的宏中,"##"被称为  连接符
//它是一种预处理运算符,用来把两个语言符号组成单个语言符号
//这里的语言符号不一定是宏的变量,"##"运算符可以将两个记号(例如标识符)“粘”在一起,成为一个记号

//例子:
#define L(x) S##x //例如L(1)就等价于S1
#define L1(x) 人##x //例如L(1)就等价于人1

#define PN(x) Etes##x //例如L(1)就等价于人1

//注意:"##"运算符不能作为第一个或者最后一个元素存在
//#define PN2(x) ##x    报错
//#define PN2(x) x##   报错(直接执行并没有错,应该##会把“报错”两个字当成一个符号)


//如果带参数的宏定义比较长,可以使用'\'连接
#define MYTRE(x) if(x>1){\
    printf("这个数值是大于1的啊\n");\
}\
else{\
    printf("这个数值其实也并不是很大嘛\n"); \
}



void go1(){
    //注意:#define 不受块语句限制
    #define Z 10.0
    //下面的main函数中仍然可以使用Z
}

void Etes1(){
    printf("我是函数Etes1\n");
}
void Etes2(){
    printf("我是函数Etes1\n");
}


void 水乃万物之源(){
    int a[X] = { 0 };
    //X = 5;  报错: 错误    1    error C2106 : “ = ” : 左操作数必须为左值    ,说明X是个常量

    //printf("%d", Y);报错:错误    2    error C2059: 语法错误:“)”
    //因为这里Y是100;

    printf("%d\n", X); 

    printf("%d\n", Z);//打印0,因为这里Z是double类型的
    //注意:宏展开只是种简单的代换,字符串中可以包含任何字符,
    //可以是常数,也可以是表达式,预处理器进行宏展开时并不进行语法检查。


    #undef X//结束X的宏定义
    //printf("%d\n", X);  报错

    //带参数的宏定义
    printf("%d\n", FL(3));

    printf("%d\n", MYMIN(3,8));//打印3

    printf("%d\n", MYTEX(1+7, 2+7));//打印22
    //注意:define只会替换,所以 MYTEX(1+7, 2+7))等价于1+7*2+7
    printf("%d\n", MYTEX2(1 + 7, 2 + 7));//打印72

    //宏定义中#的应用
    MYTEF(你好);//打印“你好”
    //宏定义中#还应用于打印变量的名字
    int a1 = 9;
    MYTEF2(a1);

    MYTRE(2)

        //"##"运算符的使用
        int L(1), L1(1);
    //这里的L(1)就是S1
    S1 = 10;
    人1 = 3;
    printf("L(1)的值是%d\n",L(1));
    MYTEF2(L1(1));
    //"##"运算符用于调用各种函数
    PN(1)();
    //PN(1)相当于Etes1


    system("pause");
}