变量的3个属性——作用域、链接属性和存储类型。
这三个属性决定了一个变量的“可视性”(它可以在什么地方使用)和“生命周期”(它的值将保持多久)。
基本数据类型
在c语言中,仅有4种基本数据类型——整型、浮点型、指针和聚合类型(如数组和结构)。所有其他的类型都是从这4种基本类型的某种组合派生的。
整型家族
整型家族包括字符、短整型、整型和长整型,它们都分为有符号(signed)和无符号(unsigned)两种版本。
听上去 “长整型”所能表示的值应该比“短整型”所能表示的值要大,但这个假设不一定正确。规定整型值相互之间大小的规则很简单。
长整型至少应该和整型一样长,而整型至少应该和短整型一样长。
注意:标准没有规定长整型必须比短整型长,只是规定它不得比短整型短。
类型 取值范围
char 0~127
signed char -127~127
unsigned char 0~255
short int -32767~32767
unsigned short int 0~65535
int -32767~32767
unsigned int 0~65535
long int -2147483647~2147483647
unsigned long int 0~4294967296
short int 至少16位,long int 至少32位,至于缺省的int 究竟是16位还是32位或是其他值,则由编译器设计者决定。通常这个选择的缺省值是这种机器的最为自然(高效)的位数。注意到标准没有规定这3个值必须不一样。如果某种机器的环境的字长是32位,而且没有什么指令能有更有效处理更短的整型值,它可能把这3个整型都设定为32位。(1个字节8位)
常用数据类型对应字节数可用如sizeof(char),sizeof(char*)等得出,也可以通过头文件limits.h查询。
枚举类型:
enum Jar_Type { cup, pint,quart };
浮点类型
浮点类型家族包括 float、double、long double 类型。头文件float.h定义了名字 FLT_MAX 、DBL_MAX 和LDBL_MAX,分别表示了float,double和long double 所能存现的最大值。
指针
变量的值存储于计算机的内存中,每个变量都占据一个特点的位置,每个内存的位置都由地址唯一确定并引用。指针只是地址的另一个名字罢了。通过地址而不是名字来访问数据。c语言拥有一些操作符,你可以获得一个变量的地址,也可以通过指针变量来获得它所指向的值或数据结构。
指针常量
指针常量和非指针常量在本质上是不同的,因为编译器负责把变量赋值给计算机内存中的位置,程序员事先无法知道某个特定的变量将存储到内存中的那个位置。因此,你通过操作符获得一个变量的地址而不是直接把它的地址写成字面值常量的形式。所以,c语言内部并没有特地定义这个概念。
char *message=”Hello World!”;
这条语句把message声明为一个指向字符串的指针,并用字符串常量中第一个字符的地址对该指针进行初始化。等价于下面的写法:
char *message;
message=”Hello World! “;
所以不要以为是给 *message赋值。
typedef
她允许你为各种数据类型定义新的名字。
typedef char *ptr_to_char;
上面那个声明把标识符 ptr_to_char 作为指向字符 的指针类型的新名字。
ptr_to_char a;//声明了a是一个指向字符的指针
作用域
编译器可以确认4种不同类型的作用域——文件作用域、函数作用域、代码块作用域和原型作用域。
代码块作用域:位于一对花括号之间的所有语句称为一个代码块。任何在代码块的开始位置声明的标识符都具有代码块作用域。表示它们可以被这个代码块中的所有语句访问。
文件作用域:任何在所有代码块之外声明的标识符都具有文件作用域。这些标识符表示从它们的声明处直到所在的源文件结尾都是可以访问的。#includet的声明作用域不仅局限于头文件的文件尾。
链接属性:一共有3种,external(外部)、internal(内部)和none(无)。
没有链接属性的标识符总是被当做单独的个体。即使该标识符有个声明。
internal 链接属性的标识符在同一个源文件内的所有声明都指向同一个实体。
external链接属性的标识符无论声明多少次,位于几个源文件都表示同一个实体。
关键字external和static用于在声明中修改标识符的链接属性。如果某个声明在正常情况下是external链接属性,在它前面加上static可以使它的链接属性变成internal。即这个源文件私有。
static int b;
存储类型
变量的存储类型(storage class):存储变量值得内存类型。
变量的存储类型决定了变量何时创建、何时销毁以及它的值将会保持多久。有三个地方可以存储变量:普通内存、运行时堆栈、硬件寄存器。
变量的缺省存储类型取决于它的声明位置。凡是在代码块之外声明的变量总是存储于静态内存中,也就是不属于堆栈的内存,这类变量称为静态变量。
静态变量在程序运行前创建,在程序的整个执行期间始终存在,且保持原先的值。
在代码块内部声明的变量的缺省存储类型是自动的。也就是说它存储于堆栈中,称为自动变量。在程序执行到声明自动变量的代码块时,自动变量才被创建,它们的值总是垃圾。当程序的执行流离开该代码块时,这些自动变量便自动销毁。当代码块再次被执行时,它们的在堆栈中所占据的内存值有可能和原先一样,也有可能不同。即使相同,你也不能保证这块内存同时不会有其他的用途。
在代码块内部声明的变量,如果加上static,可以使它的存储类型从自动类型变为静态。注意:修改变量的存储类型并不表示修改该变量的作用域。它仍然只能在该代码块内部按名字访问。
关键字register可以用于自动变量的声明。表示它们应该存储于硬件寄存器中,这类变量称为寄存器变量。通常,寄存器变量比存储于内存的变量访问起来的效率更高。
但是编译器不一定理睬register关键字。因为把这些值从堆栈中复制到寄存器中的开销大。
注:当它用于函数定义时,或用于代码块之外的变量声明时,static关键字用于修改标识符的链接属性,从external改为internal,但标识符的存储类型和作用域不受影响。
当它用于代码块内部的变量声明时,static关键字用于修改变量的存储类型,从自动变量修改为静态变量,但变量的属性链接和作用域不受影响。
总结:
具有external链接属性的实体在其他语言的术语里称为全局实体。所有源文件的所有函数均可以访问它。只要变量不是声明在代码块或函数定义内部,它在缺省情况下的链接属性为external。如果一个变量声明在代码块内部,在它前面加extern 关键字将使它所引用的全局变量。
具有external链接属性的实体总是具有静态存储类型。