你知道.c文件还需要变身成 .i .s .o/.obj 各种模样,最后才能生出.exe的文件吗? 这篇文章将带你了解 从.c到.exe,它都经历了什么

  • 程序的翻译环境和执行环境

第1种是翻译环境,在这个环境中源代码被转换为可执行的机器指令。

第2种是执行环境,它用于实际执行代码。

  • 详解:C语言程序的编译 + 链接(有一本书里面有详讲《程序员的自我修养》)

  • 预定义符号介绍

__FILE__//进行编译的源文件

__LINE__//文件当前的行号

__DATE__//文件被编译的日期

__TIME__//文件被编译的时间

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

int main()

{

printf("%s\n", __FILE__);

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

printf("%s\n", __DATE__);

printf("%s\n", __TIME__);

//printf("%s\n", __STDC__);//如果编译器遵循ANSI C,其值为1,否则未定义。但是当前的VS是不支持标准C的

return 0;

}

  • 预处理指令#define

#define 不仅仅可以定义一个标识符

还可以定义一段的代码语句

eg.

//这一段代码就形成了死循环打印M

#define M 100

#define FOR  for(;;)

int main()

{

FOR

{

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

}

return 0;

}

换行符的作用

使用宏的小细节

#define 替换规则

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

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

被替换。

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

3. 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上

述处理过程。

注意:

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

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

#和##(只能在宏里面使用)

  • 如何把参数插入到字符串中?

1.# 的作用

把printf("The value of a is %d\n",a);    中的红字a,做到灵活替换呢

#define      PRINTF(n,format)        printf("The value of "#n" is "format"\n",n)

int main()

{

    int a = 5;

    PRINTF(a, "%d");

    int b = 2;

    PRINTF(b, "%d");

    float f = 5.2;

    PRINTF(f, "%f");

    return 0;

}

2.## 的作用

##可以把位于它两边的符号合成一个符号。

它允许宏定义从分离的文本片段创建标识符。

#define ADD_TO_SUM(num, value) \

 sum##num += value;

...

ADD_TO_SUM(5, 10);//作用是:给sum5增加10.

注:

这样的连接必须产生一个合法的标识符。否则其结果就是未定义的。

  • 宏和函数的对比

  • 预处理操作符#和##的介绍

# ## 只能在宏里面使用

#n <==> "n"   #相当于“”的作用

#define PRINT(n,format) printf("The word of "#n" is "#format"\n",n)

int main()

{

int a = 0;

PRINT(a, %d);

return 0;

}

##  起链接标识符的作用

#define L(x,y) x##y

int main()

{

int qianzhuo520 = 520;

printf("%d\n", L(qianzhuo, 520));

  qianzhuo##520 <==> qianzhuo520

return 0;

}

  • 命令定义

 在gcc上才能演示,下面用两张图片来说明

  • 预处理指令#include

 #include 是用来包含头文件的

 头文件既可以用 <> 尖括号,  也可以用 ""  双引号

 <> 尖括号所包含的头文件,在库的目录中去找,

 "" 而双引号所包含的头文件,首先在谁包含这个头文件的.c文件的目录中去找,找不到再去库中找

 所以我们字节写的头文件用"",而库里的头文件用<>.这样可以减少编译器的压力,也可以更好的区分自己写的头文件和库里的头文件

  • 预处理指令#undef

当你想要移除宏定义的时候,可以用这个 #undef

#define M 100

int main()

{

printf("M=%d\n", M);

#undef M

printf("M=%d\n", M);//这里的M就已经无法在找到了

return 0;

}

  • 条件编译

#define M 100

#define N 1

int main()

{

#if N//当#if 后面所跟的常量表达式为假时,  #if和#endif 之间的代码在预编译阶段就会清理掉,不参与编译

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

#endif

return 0;

}

多分枝条件编译

int main()

{

#if !2

printf("hehe\n");

#elif 2

printf("haha\n");

#else

printf("h h h \n");

#endif

return 0;

}

defined(MAX)   判断是否定义过标识符 MAX                等价于   #ifdef M

#define M 100

int main()

{

#if defined(M)

printf("定义过\n");

#endif

#ifdef M

printf("Loved\n");

#endif

return 0;

}

没有定义过标识符

 !defined(M)  <==>  #ifndef

#if 这类条件编译可以运用到避免头文件的多次引用

需要创建一个头文件来演示

test.h

#ifndef __TEST_H__

definf __TEST_H__

int Add(int x, int y)

#endif

其实在 VS 里写头文件,它自己会加上一条语句   #pragma once,

和上面那段代码作用一样

是可以嵌套的

int main()

{

#if 1

printf("hehe\n");

#if 1

printf("haha\n");

#endif

#endif

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值