指针和数组
char a[] = "cz";定义的是一个字符串变量!
char *b = "cz";定义的是一个字符串常量!
预处理指令
预处理指令-宏定义
C语言提供的预处理指令主要有:宏定义、文件包含、条件编译
宏名和参数列表之间不能有空格,否则空格后面的所有字符串都作为替换的字符串
带参数的宏在展开时,只作简单的字符和参数的替换,不进行任何计算操作。所以在定义宏时,一般用一个小括号括住字符串的参数。
计算结果最好也用括号括起来。
带参数的宏定义与函数的区别:
1.宏定义不涉及存储空间的分配、参数类型匹配、参数传递、返回值问题。
2.函数调用在程序运行时执行,而宏替换只在编译预处理阶段进行。所以带参数的宏比函数具有更高的执行效率。
预处理指令-条件编译
在很多情况下,我们希望程序的其中一部分代码只有在满足一定条件时才进行编译,否则不参与编译(只有参与编译的代码最终才能被执行),这就是条件编译。
#if和#elif
#if condition1
code fragment
#elif condition2
code fragment
#else
code fragment
#endif
#if
和#elif
后面的条件一般是判断宏定义而不是判断变量,因为条件编译是在编译之前做的判断,宏定义也是编译之前定义的,而变量是在运行时才产生的、才有使用的意义。
#if defined()
和#if !defined()
#if
和 #elif
后面的条件不仅仅可以用来判断宏的值,还可以判断是否定义过某个宏。比如:
#define Pi 3.14
#if defined(Pi)
code fragment
#endif
#if !defined(Pi)
code fragment
#endif
#ifdef
用法和#if defined()
基本一致
#ifndef
用法和#if !defined()
基本一致
预处理指令-文件包含
#include
,它可以将一个文件的全部内容拷贝另一个文件中。
#include
直接到C语言库函数头文件所在的目录中寻找文件。
#include "file name"
系统会先在源程序当前目录下寻找,若找不到,再到操作系统的path路径中查找,最后才到C语言库函数头文件所在目录中查找
使用注意:
-
#include
允许嵌套包含,不允许递归包含。 -
#include
指令可能导致多次包含同一个头文件,降低编译效率。如:
b.h
包含a.h
,但是在main.c
中同时包含了b.h
和a.h
,此时a.h
被包含了两次,a.h
中的代码也会被声明多次,导致编译效率降低。
解决办法:
在每个头文件中添加如下代码
// a.h
#ifndef _A _H_
#define _A_H_
code fragment
#endif
// b.h
#ifndef __B_H_
#define _B_H_
code fragment
#endif
变量
C语言有丰富的数据类型和运算符,因此计算能力非常强大,计算过程中使用的值一般用变量来存储。变量也是有分类型的,不同类型的变量有不同的存储类型、不同的生命周期、不同的作用域,C语言也提供了一些关键字来设置变量的属性(比如设置存储类型、生命周期)。
变量的作用域
局部变量:
在函数内部定义的变量,称为局部变量。形式参数也属于局部变量。
全局变量:
在所有函数外部定义的变量,称为全局变量。
变量的存储类型
变量的存储类型就是指变量存储在什么地方。有3个地方可以用于存储变量:普通内存、运行时堆栈、硬件寄存器。变量的存储类型决定了变量何时创建、何时销毁以及它的值能保持多久,也就是决定了变量的生命周期。
自动变量:
自动变量是存储在堆栈中的。
静态变量:
静态变量是存储在静态内存中的,也就是不属于堆栈。
所有的全局变量都是静态变量
被关键字static修饰的局部变量也是静态变量
寄存器变量:
存储在硬件寄存器中的变量,称为寄存器变量。寄存器变量比存储在内存中的变量访问效率更高(默认情况下,自动变量和静态变量都是放在内存中的)。
被关键字register修饰的自动变量都是寄存器变量。
只有自动变量才可以是寄存器变量,全局变量和静态局部变量不行。
寄存器变量只限于int、char和指针类型变量使用。
由于计算机中寄存器数目有限,不能使用太多的寄存器变量。如果寄存器使用饱和时,程序将寄存器变量自动转换为自动变量处理
为了提高运算速度,一般会将一些频繁使用的自动变量定义为寄存器变量,这样程序尽可能地为它分配寄存器存放,而不用内存
static和extern
static和extern对函数的作用
外部函数:
如果在当前文件中定义的函数允许其他文件访问、调用,就称为外部函数。C语言规定,不允许有同名的外部函数。
内部函数:
如果在当前文件中定义的函数不允许其他文件访问、调用,只能在内部使用,就称为内部函数。C语言规定不同的源文件可以有同名的内部函数,并且互不干扰。
在编译阶段,编译器只会检测单个源文件的语法合不合理,并不检测函数有没有定义,只有在链接的时候才会检测这个函数存不存在,也就是有没有被定义。
static:
在定义函数时,在函数的最左边加上static可以把该函数声明为内部函数(又叫静态函数),这样该函数就只能在其定义所在的文件中使用。如果在不同的文件中有同名的内部函数,则互不干扰。
static也可以用来声明一个内部函数
extern:
在定义函数时,如果在函数的最左边加上关键字extern,则表示此函数是外部函数,可供其他文件调用。C语言规定,如果在定义函数时省略extern,则隐含为外部函数。
在一个文件中要调用其他文件中的外部函数,则需要在当前文件中用extern声明该外部函数,然后就可以使用,这里的extern也可以省略。
static和extern对变量的作用
extern可以用来声明一个全局变量,但是不能用来定义变量
默认情况下,一个全局变量是可以供多个源文件共享的,也就说,多个源文件中同名的全局变量都代表着同一个变量
如果在定义全局变量的时候加上static关键字,此时static的作用在于限制该全局变量的作用域,只能在定义该全局变量的文件中才能使用,跟其他源文件中的同名变量互不干扰
extern是用来声明已经定义过而且能够访问的变量。它不能用来声明在其他文件中定义的static变量。
参考:
预处理指令