常量

使用const声明常量

// 常量a
int const a;
const int a;
// 指向整型常量的指针pci
int const *pci;
// 指向整型变量的常量指针pci
int * const cpi;
// 指向整型常量的常量指针cpci
int const * const cpci;

使用#define创建名字常量

#define MAX_ELEMENTS 50

使用enum

enum {
    MAX_ELEMENTS = 50;
    ROW = 5;
    COL = 10
};

文件作用域

任何在代码块之外声明的标识符都具有文件作用域,它表示这些标识符从他们的声明之后直到它所在的源文件结尾处都可以访问。

链接属性

可以将 C 语言的不同源文件当作不同的模块,当一个可执行程序是由(不同源文件编译的目标文件)链接而形成时,标识符的链接属性决定如何处理出现在不同文件的标识符。标识符的作用域与它的链接属性有关,但不仅仅由链接属性决定。

链接属性共有3种:

  • none: 没有链接属性的标识符总是被当作单独的个体,该标识符的多个声明被当作不同的实体
  • internal: 属于 internal 链接属性的标识符在同一个源文件内的所有声明中都指向同一个实体,但位于不同源文件的多个声明则分属于不同的实体
  • external: 属于 external 链接属性的标识符不论声明多少次,位于几个源文件都表示同一个实体
typedef char *a;

int b; // b is external, 文件作用域内的声明默认为external
static int ib; // ib is internal
int c(int d) // c is external
{
    int e;
    int f(int f); // f is external
}
static int ic(int d) // ic is internal
{

}
static int i;
int func()
{
    int j;
    extern int k; // k is external
    extern int i; // i is internal, extern不会在第一次之后的声明中改变第一次声明的链接属性
}

关键字 externstatic 用于在声明中修改标识符的链接属性。如果某个声明在正常情况下具有 external 的链接属性,static 关键字可以使其链接属性变为 internal。

声明标识符时,extern 为标识符指定 external 链接属性,这可以让声明的标识符访问其他任何位置定义的这个实体。

任何带有 static 属性声明的全局变量或者函数都是模块(该源文件)私有的。

变量的存储类型

  • 运行时堆栈: (auto变量)默认情况下代码块内部声明的变量
  • 普通内存: (static变量)文件作用域内变量、用static声明的auto变量(不过修饰变量的存储类型并不修饰变量的作用域,auto变量仍然只能在该代码块内按标识符访问)
  • 硬件寄存器: register用于auto变量的声明,提示他们应该存储在机器的硬件寄存器中

整数类型

C语言只规定了数据类型的最小范围,为了无歧义的声明特定位数的整型变量,ISO C99标准在stdint.h中引入了另一套整数类型,提供了可以指定位数的声明标识符,一般提供8、16、32、64位的声明

int8_t
int16_t
uint32_t
int64_t

强制类型转换

C中强制类型转换不改变变量存储位,而只改变对这些位的解释方式

隐式转换

C中有符号类型与无符号类型变量运算或比较时,会被转换位无符号类型

移位

C语言标准未规定应该使用那种类型的右移,对于无符号数据,右移必须是逻辑的(最左端补0),对于有符号数据,可以采用逻辑或算术右移(最左端补最高有效位),但几乎所有的编译器/机器组合都对有符号数据使用算术右移。