详解编译+链接
注:推荐一本书《程序员的自我修养》
简明 Vim 练级攻略 | 酷 壳 - CoolShell
给程序员的VIM速查卡 | 酷 壳 - CoolShell给程序员的VIM速查卡 | 酷 壳 - CoolShell给程序员的VIM速查卡 | 酷 壳 - CoolShell
__FILE__ // 进行编译的源文件__LINE__ // 文件当前的行号__DATE__ // 文件被编译的日期__TIME__ // 文件被编译的时间__STDC__ // 如果编译器遵循 ANSI C ,其值为 1 ,否则未定义
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
printf("%s\n", __FILE__);
printf("%d\n", __LINE__);
printf("%s\n", __DATE__);
printf("%s\n", __TIME__);
printf("%s\n", __FUNCTION__);
int i = 0;
FILE* pf = fopen("log.txt", "a+");
if (pf == NULL)
{
perror("fopen\n");
return 1;
}
for (i = 0; i < 10; i++)
{
fprintf(pf, "%s %d %s %s %d\n",\
__FILE__, __LINE__, __DATE__, __TIME__, i);
}
fclose(pf);
pf = NULL;
//printf("%d\n", __STDC__);//不支持
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include
#define M 1000
int main()
{
int a = 10;
int b = 0;
if (a > 10)
b = M;
else
b = -M;
return 0;
}
#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏(define macro)
#define _CRT_SECURE_NO_WARNINGS
#include
#define SQUARE(X) (X*X)
#define DOUBLE(X) ((X)+(X))
int main()
{
printf("%d\n", SQUARE(3+1));
printf("%d\n", 10 * DOUBLE(4));
//printf("%d\n", 3 + 1 * 3 + 1);
//printf("%d\n", 10 * ((4) + (4)));
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include
#define PRINT(X, FORMAT) printf("the value of "#X" is "FORMAT"\n", X);
int main()
{
int a = 10;
PRINT(a, "%d");
//printf("the value of ""a"" is %d\n", a);
float f = 5.5f;
PRINT(f, "%f");
//printf("the value of "f" is ""%f""\n", f);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include
#define CAT(X,Y,Z) X##Y##Z
int main()
{
int class101101 = 100;
printf("%d\n", CAT(class, 101, 101));
//printf("%d\n", class101101);
return 0;
}
x + 1 ; // 不带副作用x ++ ; // 带有副作用
#define _CRT_SECURE_NO_WARNINGS
#include
#define MAX(X,Y) ((X)>(Y)?(X):(Y))
int Max(int x, int y)
{
return x > y ? x : y;
}
int main()
{
int a = 5;
int b = 8;
int m = MAX(a++, b++);
//int m = ((a++) > (b++) ? (a++) : (b++));
printf("a=%d b=%d\n", a, b);
printf("m=%d\n", m);
return 0;
}
宏通常被应用于执行简单的运算。比如在两个数中找出较大的一个。
#define MAX(a, b) ((a)>(b)?(a):(b))
当然和宏相比函数也有劣势的地方:
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#define MALLOC(num, type) (type*)malloc(num*sizeof(type))
int main()
{
//malloc(10*sizeof(int));
int*p = MALLOC(10, int);
//(int*)malloc(10 * sizeof(int));
return 0;
}
宏和函数的一个对比
属 性
|
#define定义宏 |
函数
|
代码长度
|
每次使用时,宏代码都会被插入到程序中。除了非常小的宏之外,程序的长度会大幅度增长
|
函数代码只出现于一个地方;每
次使用这个函数时,都调用那个
地方的同一份代码
|
执行速度
|
更快
|
存在函数的调用和返回的额外开
销,所以相对慢一些
|
操作符优级
|
宏参数的求值是在所有周围表达式的上下文环境里,除非加上括号,否则邻近操作符的优先级可能会产生不可预料的后果,所以 建议宏在书写的时候多些括号。
|
函数参数只在函数调用的时候求
值一次,它的结果值传递给函
数。表达式的求值结果更容易预
测。
|
带有副作用的参数
|
参数可能被替换到宏体中的多个位置,所以带有副作用的参数求值可能会产生不可预料的结果。
|
函数参数只在传参的时候求值一
次,结果更容易控制。
|
参数类型
|
宏的参数与类型无关,只要对参数的操作是合法的, 它就可以使用于任何参数类型。
|
函数的参数是与类型有关的,如
果参数的类型不同,就需要不同
的函数,即使他们执行的任务是
不同的。
|
调试
|
宏是不方便调试的
|
函数是可以逐语句调试的
|
递归
|
宏是不能递归的
|
函数是可以递归的
|
把宏名全部大写 函数名不要全部大写
#define _CRT_SECURE_NO_WARNINGS
#include
#define M 100
int main()
{
int a = M;
#undef M
printf("%d\n", M);
return 0;
}
调试性的代码,删除可惜,保留又碍事,所以我们可以选择性的编译
#define _CRT_SECURE_NO_WARNINGS
#include
#define PRINT 1
int main()
{
#if PRINT
printf("hehe\n");
#endif
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
#if 1==2
printf("hehe\n");
#elif 2==3
printf("haha\n");
#else
printf("heihei\n");
#endif
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include
#define TEST 0
#define HEHE 1
int main()
{
//如果TEST定义了,下面参与编译
//1
#ifdef TEST
printf("test1\n");
#endif
//2
#if defined(TEST)
printf("test2\n");
#endif
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include
#define TEST 0
#define HEHE 1
int main()
{
//如果HEHE不定义,下面参与编译
//3
#ifndef HEHE
printf("hehe1\n");
#endif
//4
#if !defined(HEHE)
printf("hehe2\n");
#endif
return 0;
}
查找头文件直接去标准路径下去查找,如果找不到就提示编译错误
先在源文件所在目录下查找,如果该头文件未找到,编译器就像查找库函数头文件一样在标 准位置查找头文件, 如果找不到就提示编译错误。
这样最终程序中就会出现两份comm.h的内容。这样就造成了文件内容的重复。
#ifndef __TEST_H__#define __TEST_H__// 头文件的内容#endif //__TESH_H__
#pragma once