1、变量的声明
声明变量的基本形式:
说明符号(一个或者多个) 声明表达式列表
说明符 (specifier) 包含一些关键字,用于描述被声明的标识符的基本类型,它也可用户改变标识符的缺省存储类型和作用域.
如:
int i;
char j, k, l;
修改变量的长度或者是否为有符号数的关键字:
//short long signed unsigned
unsigned short int a;
unsigned short a;
相等的整型说明
有符号 | 无符号 |
---|---|
short signed short | unsigned short |
short int signed short int | unsigned short int |
int signed int | unsigned int |
signed | unsigned |
long signed long | unsigned long |
long int signed long int | unsigned long int |
2、指针的声明
几个需要注意的点
//正常的声明一个指向整型指针
int *a;
//也可以这样写, *与int 类型标识符贴近.
int* a;
//需要注意的是 只有b 是整型指针, c,d是整型
int *b, c, d;
//只有*紧贴变量名时才使得 b,c,d 都是指向整型的指针
int *b, *c, *d;
//声明+初始化一个字符串
char *message = "hello world!";
//上句相当于这两行代码
char *message;
message = "hello world!";
3、typedef
typedef 允许程序员为各种数据类型定义新的名字
例如:
//声明一个指向字符的指针prt_to_char
char *prt_to_char;
//用typedef 把 prt_to_char作为指向字符的指针类型的新名字.
typedef char *ptr_to_char;
//可以使用这个新名字定义 指向字符的指针
ptr_to_char a;
注意:应该使用typedef 而不是 #define 来创建新的类型名 ,因为后者无法处理指针类型
定义复杂的类型名字时应该使用typedef 如:函数指针或者指向数组的指针
4、常量
ANISI C允许声明常量.
常量的样子和变量完全一样,只是不能被修改.声明时使用const关键字.
如
//常量的声明,但是无法被更改
int const a;
const int a;
//所以常量声明和定义是一起的
int cosnt a = 1;
//当涉及指针变量时,需要注意
//pi 是一个普通的指向整型的指针,
int *pi;
//pic 是一个指向整型常量的指针.你可以修改指针的值,但你不能修改它所指向的值.
int const *pic;
//pcc 为指向整型的常量指针.此时指针是常量,它的值无法被修改,但你可以修改它所指向的整型的值.
int * const pcc;
//cc无论是指针还是它所指向的值都是常量,不允许修改
int const * const * cc;
*cosnt 的结合是从右往左的,如 int const pcc; const修饰,指针是不能被修改的.又如 int const pic ,指针所指的值是不能被修改的
#define 也是可以定义常量的, 用字面值的地方都可以用 #define 来定义
5、作用域 scope
变量在程序的某个部分被声明的时候,它只有在程序的一定区域才能被访问. 这个区域由标识符作用域决定.
编译器可以确认4中不同类型的作用域:
文件作用域、函数作用域、代码块作用域、原型作用域
6、链接属性
链接属性一共有3种:external(外部)、internal(内部)、none(无)
没有链接属性的标识符(none )总是被当作单个个体,也就是该标识符的多个声明被当作独立不同的实体.
属于internal链接属性的标识符在同一个源文件的所有声明中都指向同一个实体,但位于不同源文件的多个声明则分属不同的实体.
属于 external 链接属性的标识符不论声明多少次,位于几个源文件都标示同一个实体.
关键字 extern 和 static 用于在声明中修改标识符的链接属性.如果某个声明在正常情况下具有 extrenal 链接属性,在它前面加上 static 关键字可以使它的链接属性变为 internal.
如
// b 的作用域变为该源文件所私有
static int b;
//函数 foo的作用域为它所在的源文件所私有, 可以防止它被其他源文件调用
static int foo(int d);
7、存储类型
变量的存储类型是指存储变量值的内存类型.
存储类型决定来变量何时创建、何时销毁、以及它的值保持多久.
变量存储的三个地方:普通内存、运行时堆栈、硬件寄存器.
变量的缺省存储类型取决于它的声明位置.
凡是在任何代码块之外声明的变量,总是存储与静态内存中,也就是不属于堆栈的内存,这类变量称为静态(static)变量.对于这类变量,你无法为他们指定其他存储类型. 静态类型在程序运行之前创建,在程序的整个执行期间始终存在.它始终保持原先的值,除非给它赋一个不同的值或者程序结束.
在代码块内部声明的变量的缺省存储类型都是自动(automatic), 也就是说它存储于堆栈中,称为自动(auto)变量.一个函数被多次调用,它内部的自动变量会被多次创建和销毁.对于在代码块内部声明的变量,如果给它加上static关键字,可以使它的存储类型从自动变为静态.具有静态存储类型的变量在整个程序执行过程中一致直存在,而不仅仅在声明它的代码块的执行时存在.
注意:修改变量的存储类型,并不代表修改变量的作用域,它仍然只能在该代码内部按名字访问.函数的形式参数不能声明为静态,因为实参总是在堆栈中传递参数,用于支持递归
关键字register可用于自动变量的声明,提示它们应该存储于机器的硬件寄存器而不是内存中,这类变量称为寄存器变量.通常,寄存器变量比存储于内存的变量访问起来效率更高.但是编译器并不一定要理睬 register关键字,如果有太多的变量被声明为 register, 它只选取前几个实际存储于寄存器中,其余的就按照普通自动变量处理.
8、static 关键字
特别提醒: 不同的上下文环境,static关键字具有不同的作用
-当它用与函数定义时,或用于代码块之外的变量声明时,static 关键字用于修改标识符的链接属性, 从 external 改为 internal, 但标识符的存储类型和作用域不受影响.用这种方式声明的函数或变量只能在声明他们的源文件内部访问.
-当它用于代码块内部的变量时, static关键字用于修改变量的存储类型,从自动变量修改为静态变量,但变量的链接属性和作用域不受影响.用这种方式声明的变量在程序执行之前创建,并在程序的整个执行期间一致存在,而不是每次在代码块开始执行是创建,在代码块执行完毕后销毁.
9、作用域、链接属性、存储类型总结
变量类型 | 声明的位置 | 是否存于堆栈 | 作用域 | 如果声明为static |
---|---|---|---|---|
全局 | 所有代码块之外 | 否 | 从声明处到文件尾 | 不允许从其他源文件访问 |
局部 | 代码块起始处 | 是 | 整个代码块 | 变量不存储于堆栈中,它的值在真个执行期一直保持 |
形式参数 | 函数头部 | 是 | 整个函数 | 不允许 |