预处理指令、typedef、static和extern

1.预处理指令

C编译器在对源程序进行编译之前,会进行编译预处理。这一步骤由C预处理器(C Preprocessor)完成。所有的预处理器命令都以#开头。预处理指令可以出现在程序的任何位置,它的作用范围是从它出现的位置到取消它的预处理出现位置或文件末尾。

指令 描述
#define 定义一个预处理宏
#undef 取消宏定义
#ifdef 判断某个宏是否已定义,若已定义,则执行后续语句
#ifndef 判断某个宏是否未定义,若未定义,则执行后续语句
#if 条件判断,同C语句中的if
#elif 条件判断,同C语句中的else if
#else 条件判断,同C语句中的else
#endif 条件判断结束语句,#ifdef、#ifndef‘、#if结尾
#include 包含文件命令
#line 标志该语句所在行号和文件名
#warning 显示编译器警告信息
#error 显示编译器错误信息
#pragma 说明编译器信息

预定义宏

ANSI C定义了许多宏

描述
FILE 当前文件名,类型为字符串常量
LINE 当前行号,类型为十进制常量
DATE 当前日期,类型为字符串常量,格式“MMM DD YYYY”
TIME 当前时间,类型为字符串常量,格式“HH:MM:SS”

实例:

printf("File :%s\n", __FILE__ );
printf("Line :%d\n", __LINE__ );
printf("Date :%s\n", __DATE__ );
printf("Time :%s\n", __TIME__ );

运行结果:

File :main.c
Line :6
Date :May 10 2016
Time :15:16:55

预处理器运算符号

(1)宏延续运算符(\)

一个宏太长,在当行容纳不下是,可使用宏延续运算符(\),使其延续到下一行。

(2)字符串常量化运算符(#)

在宏定义中,需要把一个宏的参数转换为字符串常量时使用。

(3)标记粘贴运算符(##)

在宏定义中,可以使宏定义中两个地理的标记被合并为一个标记

(4)defined()运算符

用于确定一个标识符是否已经使用#define定义过。定义则为真,为定义则为假。

实例:

#define THREE1 3
#define add(a,b)     printf(#a" add "#b " = %d",THREE##a)

int main(int arg,char *argv[]){
    #if defined THREE1
        add(1,2);
    #endif // defined
    return 0;
}

运行结果:

1 add 2 = 3

宏定义

(1)不带参数的宏定义

格式:#define 宏名称 字符串

#define COUNT 5

效果:在编译预处理时,会将宏名称替换为对应的字符串。常用用于定义常量和防止头文件重复加载。

实例:

#ifndef _FILE_INT_
#define _FILE_INT_
#include "int.h"
#endif // _FILE_INT_

(2)带参数的宏定义

格式:#define 宏名称(形参一,形参二,....) 字符串

#define sum(num1,num2) ((num1)+(num2))

效果:同上

(3)宏取消

格式:#undef 宏名称

(4)使用注意

编译预处理只会执行简单的替换操作,不会进行逻辑运算。

(5)与函数运算的区别

宏定义不涉及存储空间的分配,是在编译之前进行的,故彼函数执行效率更高。

条件编译

控制部分代码是否参与编译(只有被编译的代码被执行)。

格式:

#if 条件1
        执行语句1
    #elif 条件2
        执行语句2
    #else 条件3
        执行语句3
    #endif

文件包含

将一个文件的全部内容拷贝到目标文件中

(1)#include <文件名>

直接在C语言函数库头文件所在的目录中寻找文件

(2)#inlcude "文件名"

一次在源程序当前目录下->系统path路径中->C语言库函数文件所在目录寻找。

#line

可用于修改__LINE和__FILE__

 #line 1 "linechange.c"
    printf("line:%d, flie:%s\n",__LINE__,__FILE__);

运行结果:

line:1, flie:linechange.c

#warning,#error

分别用于在编译时显示警告和错误信息

格式:#warning “warning”;#error “error”

ps:如果给出的是warning编译会继续,是error编译会终止

2.typedef

用于为类型取一个新的名字。它由编译器执行解释。

实例:

typedef char * string;
string str = "字符串";
printf("%s",str);

也可以用于用户自定义的数据类型取一个新名字。

typedef struct Books
    {
       char  title[50];
       char  author[50];
       char  subject[100];
       int   book_id;
    } Book;
Book book;

3.extern和static

作用于变量

(1)extern

在方法体中,带有关键字extern的变量。可以在别的方法和文件中进行访问。

(2)static

带有关键字static的全局变量为私有全局变量,仅限于当前文件访问。

带有关键字static的局部变量,只会创建一次,且生命周期至程序结束时。

实例:

int main(int arg,char *argv[]){
   for(int i = 0;i < 5;i ++)
   {
       test();
   }
   return 0;
}
void test(){
    static int a = 0;
    a ++;

    int b = 0;
    b ++;
    printf("a = %d\tb = %d\n",a,b);

运行结果:

a = 1   b = 1
a = 2   b = 1
a = 3   b = 1
a = 4   b = 1
a = 5   b = 1

作用于函数

(1)extern

表示函数为外部函数可以在其他文件中使用。extern关键字可省略。

(2)static

申明函数为内部函数(或静态函数),只能在其定义的文件中使用。

时间: 2024-11-22 19:29:30

预处理指令、typedef、static和extern的相关文章

黑马程序员————C语言(预处理指令、static与extern、typedef)

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 第一讲  预处理指令 预处理指令的概述 C语言在对源程序进行编译之前,会先对一些特殊的预处理指令作解释,比如之前使用的#include文件包含指令,产生一个新的源程序,这个过程称为编译预处理,之后再进行通常的编译 为了区分预处理指令和一般的C语句,所有预处理指令都以符号"#"开头,并且结尾不用分号 预处理指令可以出现在程序的任何位置,它的作用范围是从它出现的位置到文件尾.习惯上我们尽

typedef , static和 extern

typedef 1.作用:给已经存在的类型起一个新的名称 2.使用场合: 1> 基本数据类型 2> 指针 3> 结构体 4> 枚举 5> 指向函数的指针 #include <stdio.h> typedef int MyInt; typedef MyInt MyInt2; // 给指针类型char *起一个新的类型名称String typedef char * String; /* struct Student { int age; }; typedef stru

c语言预处理指令、typedef、static和extern相关介绍

一:typedef 作用:可以给一个已经存在的数据类型取一个别名 格式:typedef 原数据类型  新类型   例如:typedef   int  INT; 预处理指令#define 也可以给数据类型取别用用法:  #define  INT  int; //1.用在基本数据类型上 int a = 10; typedef int TNT; typedef char CHAR; CHAR c='A'; //65 TNT b = 100; //2.给数组起别名 char ch[5]; typedef

黑马程序员--C语言--预处理指令、枚举、Typedef、递归函数、变量作用域

一.预处理指令 1>所有的预处理指令都是以#号开头; 2>预处理指令是在代码翻译成0,1之前执行: 3>预处理指令最后没有分号: 4>预处理指令的位置可以随便写: 5>预处理指令有作用域,从编写指令的那一行开始,一直到文件结尾,可以用#undef取消宏定义的作用: 预处理指令分3种 1> 宏定义 2> 条件编译 3> 文件包含 二.宏定义 1. 宏定义命名规则: 1>大写字母 1 #define COUNT 2>k开头首字母大写 #define 

C的typedef声明与#预处理指令

1 typedef:给已有的类型声明新的名称,并不能创建新的数据类型: 1.1 typedef 声明 typedef unsigned char BYTE ; /* 将 unsigned char 重新命名为BYTE ;*/ typedef char * STRING ; /*将 char * 声明为STRING */ 1.2 typedef与#define typedef char * STRING; STRING name, course; //等价于 char * name , * cou

C语言-1.结构体,2.枚举,3.typedef,4.预处理指令的概念,5.条件编译

1. 结构体数组 定义:由若干个相同类型的结构体变量组成的有序的集合. 定义格式: 1) 定义结构体的同时定义结构体数组 struct Car{ int lunzi; int speed; }cars[5]; 2) 使用匿名结构体定义数组 struct { int lunzi; int speed; }cars[5]; 3)先定义结构体,再定义结构体数组 struct Car cars[5]; 初始化: 1) 定义结构体数组的同时进行初始化 struct Car{ int lunzi; int

黑 马 程 序 员_视频学习总结&lt;C语言&gt;----07 static和extern关键字、typedef

---------------------- ASP.Net+Unity开发..Net培训.期待与您交流! ---------------------- 一.外部函数 外部函数:如果在当前文件中定义的函数允许其他文件访问.调用,就称为外部函数.C语言规定,不允许有同名的外部函数 二.内部函数 内部函数:如果在当前文件中定义的函数不允许其他文件访问.调用,只能在内部使用,就称为内部函数.C语言规定不同的源文件可以有同名的内部函数,并且互不干扰. 三.static.extern与函数的总结 1.在定

黑马程序员— C语言基础之结构体、枚举、预处理、typedef的使用

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 本章我们主要来学习之前所学的复杂数据类型中的同样也很重要的结构体和枚举的知识,以及C语言中的预处理,typedef的使用,简单介绍一下static和extern等一些比较杂的知识.在开始本章的新知识学习之前首先我们来学习一下根据变量的作用域的不同C语言一般把变量分为两种,局部变量和全局变量.下面我们来分别比较和体会一下这两种不同的变量类型: 根据变量的作用域,可以分为: 1. 局部变量: a.

OC高效率52之多用类型常量,少用#define预处理指令

// //  ViewController.m //  OC高效率52之多用类型常量,少用#define预处理指令 /**  *     1. 不要用预处理定义常量.这样定义出来的常量不含类型信息,编译器只是会在编译前据此执行查找与替换操作.即时有人重新定义了常量值,编译器也不会产生警告信息,这将导致应用程序中得常量值不一致.        2.在实现文件中使用static const 来定义"只在编译单元内可见的常量".由于此类常量不在全局符号表中,所以无需为其名称加前缀.