C语言编程(1)—— 预处理命令

预处理

什么是预处理

 在编译之前对源文件进行简单加工的过程,就称为预处理(即预先处理、提前处理)。以#开头的命令为预处理命令。
 预处理是C语言的一个重要功能,由预处理程序完成。当对一个源文件进行编译时,系统将自动调用预处理程序对源程序中的预处理部分作处理,处理完毕自动进入对源程序的编译。编译器会将预处理的结果保存到和源文件同名的.i文件中,例如 main.c 的预处理结果在 main.i 中。和.c一样,.i也是文本文件,可以用编辑器打开直接查看内容。

#include

功能特点

 #include 为文件包含命令,用来引入对应的头文件。#include 的处理过程就是将头文件的内容插入到该命令所在的位置,从而把头文件和当前源文件连接成一个源文件,这与复制粘贴的效果相同。

<> 与“”的区别

 使用尖括号< >和双引号" “的区别在于头文件的搜索路径不同:
 使用尖括号< >,编译器会到系统路径下查找头文件;比如标准库文件等
 使用双引号” ",编译器首先在当前目录下查找头文件,如果没有找到,再到系统路径下查找。一般情况我们自定义的头文件用双引号引用。

注意

 同一个头文件可以被多次引入,但是多次引入的效果和一次引入的效果相同,因为头文件在代码层面有防止重复引入的机制
 文件包含允许嵌套,即在一个被包含的文件中又可以包含另一个文件。
 不管是标准头文件,还是自定义头文件,都只能包含变量和函数的声明,不能包含定义。在头文件中定义定义函数和全局变量这种认知是原则性的错误!否则在多次引入时会引起重复定义错误。

#define

功能特点

 #define 叫做宏定义命令。即用一个标识符来表示一个字符串,如果在后面的代码中出现了该标识符,那么就全部替换成指定的字符串。
 宏定义的本质是在编译之前进行简单的替换,不对表达式进行任何的计算。
 宏定义中的宏名是标识符的一种,命名规则和变量相同。字符串可以是数字、表达式、if 语句、函数
 宏定义不是说明或语句,在行末不必加分号,如加上分号则连分号也一起替换
 宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结束。如要终止其作用域可使用#undef命令

带参数的宏定义

带参宏定义的一般形式:#define 宏名(形参列表) 字符串
带参宏调用的一般形式为:宏名(实参列表);
特点:
 a、对带参数的宏,在展开过程中不仅要进行字符串替换,还要用实参去替换形参(先替换字符串、再替换参数)
 b、在带参宏定义中,不会为形式参数分配内存,因此不必指明数据类型.

带参宏定义和函数的区别

区别:
 a、宏展开仅仅是字符串的替换,不会对表达式进行计算。且宏在编译之前就被处理掉了,它没有机会参与编译,也不会占用内存。
 b、函数是一段可以重复使用的代码,会被编译,会给它分配内存,每次调用函数,就是执行这块内存中的代码。

宏参数的字符串化和宏参数的连接(#和##)

#的用法和特点

 #用来将宏参数转换为字符串,即在宏参数的开头和末尾添加引号
实例:

#include <stdio.h>

#define S(string) #string

int main()
{
	printf("%s\n", S(abcdefg)); 	// 打印输出 "abcdefg"
	printf("%s\n", S("abcdefg"));   // 打印输出 "\"abcdefg\""
	return 0;
}

##的用法和特点

 ##称为连接符,用来将宏参数或其它的字符串连接起来

#include <stdion.h>

#define CONNECT_1(a, b) a##e##b##
#define CONNECT_2(a, b) a##b##56

int main()
{
	printf("%f\n", CONNECT_1(1.234, 3));	// 被展开为1.234e3    打印输出 1234.000000
	printf("%d\n", CONNECT_2(12, 34));	    // 被展开为123456     打印输出 123456
	return 0;
}

条件编译

什么是条件编译

  能够根据不同情况编译不同代码、产生不同目标文件的机制,称为条件编译。条件编译是预处理程序的功能,不是编译器的功能

实例

  a、输出红色的文字,并且要求跨平台,在 Windows 和 Linux 下都能运行,这个程序的难点在于,不同平台下控制文字颜色的代码不一样,我们必须要能够识别出不同的平台。Windows 有专有的宏_WIN32,Linux 有专有的宏__linux__

#include <stdio.h>
int main(){
    #if _WIN32
        system("color 0c");
        printf("http://c.biancheng.net\n");
    #elif __linux__
        printf("\033[22;31mhttp://c.biancheng.net\n\033[22;30m");
    #else
        printf("http://c.biancheng.net\n");
    #endif

    return 0;
}

  b、VS/VC 有两种编译模式,Debug 和 Release。在学习过程中,我们通常使用 Debug 模式,这样便于程序的调试;而最终发布的程序,要使用 Release 模式,这样编译器会进行很多优化,提高程序运行效率,删除冗余信息。

#include <stdio.h>
#include <stdlib.h>
int main(){
    #ifdef _DEBUG
        printf("正在使用 Debug 模式编译程序...\n");
    #else
        printf("正在使用 Release 模式编译程序...\n");
    #endif

    system("pause");
    return 0;
}

  当以 Debug 模式编译程序时,宏 _DEBUG 会被定义,预处器会保留第 5 行代码,删除第 7 行代码。反之会删除第 5 行,保留第 7 行。

#if 用法的一般格式

#if 整型常量表达式1
  程序段1
#elif 整型常量表达式2
  程序段2
#elif 整型常量表达式3
  程序段3
#else
  程序段4
#endif

#ifdef 用法的一般格式为:

#ifdef 宏名
  程序段1
#else
  程序段2
#endif

#ifndef 用法的一般格式为:

#ifndef 宏名
  程序段1
#else
  程序段2
#endif

注意:#if 后面跟的是“整型常量表达式”,而 #ifdef 和 #ifndef 后面跟的只能是一个宏名,不能是其他的

#error命令

功能特点

  #error 指令用于在编译期间产生错误信息,并阻止程序的编译。形式为

#error error_message

实例

  a、我们的程序针对Linux编写,不保证兼容Windows

#ifdef WIN32
#error This programme cannot compile at Windows Platform
#endif

  WIN32 是Windows下的预定义宏。当用户在Windows下编译该程序时,由于定义了WIN32这个宏,所以会执行 #error 命令,提示用户发生了编译错误,错误信息是:

This programme cannot compile at Windows Platform

  b、当我们希望以C++的方式来编译程序

#ifndef __cplusplus
#error 当前程序必须以C++方式编译
#endif

注意:报错信息不需要加引号 " " ,如果加上,引号会被一起输出

C语言中几个常用的预定义宏

 __ LINE__:   表示当前源代码的行号;
 __ FILE__:   表示当前源文件的名称;
 __ DATE__:  表示当前的编译日期;
 __ TIME__:   表示当前的编译时间;
 __ STDC__:  当要求程序严格遵循ANSI C标准时该标识被赋值为1;
 __ cplusplus: 当编写C++程序时该标识符被定义。
 __ FUNCTION__(或者__func__):表示当前的调用的函数名称

附录

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值