《C和指针》学习总结。
数据
变量具有作用域,链接属性和存储类型三个属性,这三个属性决定了一个变量的“可视性”与“生命周期”。
在C语言中,仅有4种基本数据类型:“整型”,“浮点型”,“指针”和“聚合类型(数组,结构体等)”。所有其他的类型都是从这4种基本类型的某种组合派生而来。
整型
整型包括字符,短整型,整型和长整型,它们都分为有符号(signed)和无符号(unsigned)两种版本。
长整型至少应该和整型一样长,而整型至少应该和短整型一样长。
typedef
c语言支持 typedef
来为各种数据类型定义新名字。
1 | typedef char *ptr_to_char; |
2 | ptr_to_char a; |
应该使用 typedef
而不是 #define
来创建新的类型名,因为后者无法正确地处理指针类型。
1 |
|
2 | d_ptr_to_char a, b; //只有a声明为指针,b却被声明为一个字符。 |
define
指令是另一种创建名字常量的机制。
1 |
|
2 | int const max_elements = 50; |
3 | |
4 | char hello[MAX_ELEMENTS]; /* const变量只能使用于允许使用变量的地方 */ |
常量
ANSI C使用 const
关键字声明常量,它们的值不能修改,可以在定义时初始化或者函数被调用时得到实参的值。
1 | int const a; |
2 | const int a; |
当const
与指针结合会影响指针变量或者它所指向的实体。
1 | int *pi; /* 普通指针 */ |
2 | int const *pci; /* 指向整型常量的指针,可以修改指针的值,但不可修改它所指向的值 */ |
3 | const int *pci; /* 同上 */ |
4 | int * const cpi; /* 指向整型的常量指针,指针是常量不可修改,它所指向的整型值可修改 */ |
5 | int const * const cpci; /* 指针本身与它所指向的值都不可被修改 */ |
作用域
编译器可以确认4种不同类型的作用域-文件作用域,函数作用域,代码块作用域和函数原型作用域。
位于一对花括号之间的所有语句称为一个代码块。函数定义的形式参数在函数体内部也具有代码块作用域。函数体内部声明了与形参相同的局部变量,形参将被隐藏,无法被访问。应该避免在嵌套的代码块中使用相同的变量名。
在所有代码块之外声明的标识符都具有文件作用域(file scope),它表示这些标识符从它们的声明之处直到它所在的源文件结尾处都可以访问。在文件中定义的函数名也具有文件作用域。在头文件中编写并通过 #include
指令包含到其他文件中的声明就好像它们是直接写在那些文件中一样,他们的作用域不局限于头文件的文件尾。
链接属性
标识符的链接属性(linkage)决定如何处理在不同文件中出现的标识符。
链接属性一共有3种:external(外部),internal(内部),none(无)。没有链接属性的标识符(none)总是被当作单独的个体,也就是说该标识符的多个声明被当作独立不同的实体。属于 internal 链接属性的标识符在同一个源文件内的所有声明中指同一个实体,但是为于不同源文件的多个声明则分属不同的实体,属于 external 链接属性的标识符不论声明多少次,位于几个源文件都表示同一个实体。
关键字 extern
和 static
用于在声明中修改标识符的链接属性。如果某个声明在正常情况下具有 external 链接属性,在它前面加上 static
关键字可以使它的链接属性变为 internal。
static
只对缺省链接属性为 external 的声明才有改变链接属性的效果。extern
关键字为一个标识符指定external链接属性。
存储类型
变量的存储类型(storage class)是指存储变量值的内存类型。决定变量何时创建,何时销毁以及它的值将保持多久。
存储变量的三个地方:普通内存,运行时堆栈,硬件寄存器。
变量的缺省存储类型取决于它的声明位置。凡是在任何代码块之外声明的变量总是存储于静态内存中,这类变量称为静态(static)变量(main函数里声明的变量也是局部变量)。在代码块内部声明的变量的缺省存储类型是自动的(automatic),存储在堆栈中,称为自动(auto)变量。
代码块内部声明的变量加上static关键字,则使它的存储类型从自动变为静态。修改变量的存储类型并不表示修改该变量的作用域。
函数的形参不能声明为静态,因为实参总是在堆栈中传递给函数,用于支持递归。
static关键字
当 static
关键字用于函数定义时,或用于代码块之外的变量声明时,static
关键字用于修改标识符的链接属性,从external改为internal,但标识符的存储类型和作用域不受影响。用这种方式声明的函数或变量只能在声明它们的源文件中访问。
当 static
关键字用于代码块内部的变量声明时,static
关键字用于修改变量的存储类型,从自动变量改为静态变量,但变量的链接属性和作用域不受影响。用这种方式声明的变量在程序执行之间创建,并在程序的整个执行期间一直存在,而不是每次在代码块开始执行时创建,在代码块执行完毕后销毁。