03 数据

程序数据进行操作。

3.1 作用域、链接属性和存储类型

变量有三个属性,这三个属性决定了一个变量的可视性和生命期

  • 作用域

  • 链接属性

  • 存储类型

作用域

  • 代码块作用域

  • 函数作用域

  • 函数原型作用域,只适用于在函数原型中声明的参数名。

  • 文件作用域,注意如果一个文件被include到了另一个文件中,则文件作用域还包含了使用include的那个文件

链接属性

C 变量有3种链接属性:

  • 外部链接:外部链接变量可以在多文件程序中使用

  • 内部链接:在一个翻译单元中使用

  • 无链接:变量属于定义他们的块或函数或原型私有。(块、函数、函数原型作用域三种变量是无链接的,也就是说,只有文件作用域的变量会有内部和外部链接)

文件作用域变量的默认链接属性是外部链接。但是如果再加上static关键字,则会变成内部链接。给非文件作用域的变量加extern会让其引用同名的全局变量。

存储类型

  • 静态内存:文件作用域变量和static修饰的函数中的变量存储在静态内存中。

  • 运行时堆栈

  • 寄存器变量

现在很多编译器会自动优化。

注意static两个完全不同的意义:

  • 修饰函数或者文件作用域的变量时,会把其链接属性从external变为internal。

  • 修饰代码块和函数内的变量时,会把变量的存储类型变成static,但是链接属性和作用域不变。

3.2 基本数据类型

C语言中仅有最基础的四种类型:

  • 整型

    包括字符、短整型、整型和长整型。limits.h中说明了它们的最大和最小范围。另外枚举类型的值是符号常量,声明为枚举类型的变量实际上也是整型。

  • 浮点型

    包括float、double、long double,float.h中包含了它们的范围。浮点数字面值默认都是double类型,后面跟l或L则是long double,跟f或F则是float类型。

  • 指针 当一个字符串常量出现在表达式中时,表达式用的值是这些字符所存储的地址。因此,可以把字符串常量赋值给一个”指向字符的指针“。如

    char *message = "Hello world!";
  • 聚合类型(包括数组和结构体)

3.3 指针使用的两点注意

一是关于声明,二是指针和常量的组合使用。

关于指针的声明有两点需要注意。一是下面这种写法,只有a是指针,b和c都是整型。所以建议声明时,指针写在后面。

int* a, b, c;

声明三个指针正确的写法:

int *a, *b, *c;

c++中常量和引用搭配只有两种情况,因为引用本身是从一而终不能变的。但是c中指针和const的组合有三种情况

  • 指向整型常量的指针:指针本身可以改,但是不能改指向的值

    int const *pci;
  • 指向整型的指针常量(const在星后,则为修饰指针):指针不能改,但是可以改指向的值

    int *const int;
  • 指向整型常量的指针常量:都不能改。

    int const *const int;

3.3 typedef创建新的类型名称

在创建新的类型名时,应该用typedef而不是#define

typedef char *ptr_to_char;
ptr_to_char a; // a是一个指向char的指针

如果我们要声明多个指针,用#define的话会出错

#define d_ptr_to_char char *;
d_ptr_to_char a, b; // 只有a是指针,b是字符类型