宏定义
宏定义通常有三种用法:
- 当作常量使用
- 当作函数使用
- 编译预处理
1. 宏定义常量
预定义宏:
预定义宏 | 作用 |
---|---|
__LINE__ | 当前所在文件的行号 %d |
__FILE__ | 表示当前源文件 %s |
__DATE__ | 文件被编译的日期 %s |
__TIME__ | 文件被编译的时间 %s |
测试:
#include <stdio.h>
int main(){
printf("%s:%d\n",__FILE__,__LINE__);
printf("%s:%s\n",__DATE__,__TIME__);
}
结果为:
def5.c:4
Apr 4 2021:05:50:11
自定义宏:
本质就是做替换
#define PI 3.1415926
注意:后面没分号
2. 代参数的宏
与函数不同,不用定义也能直接改变数值,因为宏定义的本质是替换
#include <stdio.h>
#define NUM 5
#define SWAP(n,m) \
int t=n; \
n=m; \
m=t;
#define ARR_SIZE(arr) sizeof(arr)/sizeof(arr[0])
#define SQUARE(x) x*x
#define CUBE(x) x*x*x
int main(){
int a = 10;
int b = 20;
printf("a:%d\tb:%d\n",a,b);
SWAP(a,b);
printf("a:%d\tb:%d\n",a,b);
int arr[NUM];
printf("%d\n",sizeof(arr)/sizeof(arr[0]));
printf("%d\n",ARR_SIZE(arr));
printf("%d\n",SQUARE(8));
printf("%d\n",CUBE(3));
}
结果为:
a:10 b:20
a:20 b:10
5
5
64
27
得最小值或最大值,也可以使用宏定义完成
#define MIN(a,b) ((a)<(b)?(a):(b))
边际效应:
问题:
printf("%d\n",CUBE(3+2));
会造成 3+2*3+2*3+2
解决:
需要加括号
#define CUBE(x) ((x)*(x)*(x))
3. 编译预处理
#ifdef TEST
如果定义了 TEST ,则编译第一部分
如果没有定义 TEST ,则编译第二部分
#include <stdio.h>
// #define TEST
int main(){
#ifdef TEST
printf("123\n");
#else
printf("abc\n");
#endif
}
结果为:
[admin@localhost cfile]$ gcc def2.c -o def2
[admin@localhost cfile]$ ./def2
abc
如果没有定义 TEST 也可以在编译时后面加 -DTEST ,表示定义了 TEST
[admin@localhost cfile]$ gcc def2.c -o def2 -DTEST
[admin@localhost cfile]$ ./def2
123
#ifndef TEST
如果没定义 TEST ,则编译第一部分
如果定义了 TEST ,则编译第二部分
头文件
1. 文件拆分
学生登陆系统拆分:
把注册登录功能和其他功能分两部分拆分
- 结构体(剪切)、函数声明(函数内容不用),都放在 login.h
结构体(剪切)、函数声明(函数内容不用),都放在 student.h - 先把注册登陆部分的放在login.c,需要头文件,并加 #include “login.h”
把学生信息部分的放在student.c,需要头文件,并加 #include “student.h” - gcc -c login.c 生成 login.o
gcc -c student.c 生成 student.o - 在main函数文件中写头文件
#include “login.h”
#include “student.h” - 编译时 gcc main.c login.o student.o -o stud
也可以 gcc -c main.c 生成 main.o,编译时 gcc main.o login.o student.o ,相当于连接所有编译文件
login.c 文件内容
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "login.h"
//录入注册信息
bool RegisterUser(const char* path){
printf("首次登陆需要注册\n");
User current;
printf("注册用户名:");
scanf("%s",current.name);
printf("注册密码:");
scanf("%s",current.password);
FILE* pf = fopen(path,"w");
if(NULL == pf){
return false;
}
fprintf(pf,"%s %s",current.name,current.password);
fclose(pf);
pf = NULL;
return true;
}
//验证用户和密码是否正确
bool Login(const char* path){
FILE* pf = fopen(path,"r");
if(NULL == pf){
//如果没存过用户信息,则存用户信息
return RegisterUser(path); //第一次登陆要注册,注册成功直接进入
}
printf("Login...\n");
User current;
printf("请输入用户名:");
scanf("%s",current.name);
printf("请输入密码:");
scanf("%s",current