引入部分:
- 指针是C语言流行的重要原因。
- 指针可有效地实现诸如 tree 和list这类高级数据结构。其他有些语言,如Pascal 和Modula-2,也实现了指针,但它们不允许在指针上执行算术或比较操作,也不允许以任何方式创建指向已经存在的数据对象的指针。
- C语言优越性:不存在以上这些方面的限制,可编写出更紧凑有效的程序。同时,C对指针使用的不加限制也是容易出错的原因之一。
- 变量的值存储于计算机的内存中,每个变量都占据一个特定的位置。每个内存位置都由地址唯确定并引用,指针只是地址的另一个名字。指针变量就是一个其值为另外一个(一些)内存地址的变量。
- C语言拥有一些操作符:①可以获得一个变量的地址②可通过一个指针变量取得它所指向的值或数据结构
一.指针常量(pointer constant)
- 指针常量与非指针常量在本质上不同:因为编译器负责把变量赋值给计算机内存中的位置,程序员事先无法知道某个特定的变量将存储到内存中的哪个位置。
- 因此,你通过操作符获得一个变量的地址而不是直接把它的地址写成字面值常量的形式。也就是说:如果希望知道变量的地址,我们无法书写字面值,因为我们不知道这是不是编译器实际存放这个变量的内存位置。
- 事实上,当一个函数每次被调用时,它的自动变量(局部变量)可能每次分配的内存位置都不相同。
- 因此,把指针常量表达为数值字面值的形式几乎没有用处,所以C语言内部并没有特地定义这个概念。
二、字符串常量(string literal)
- C语言不存在字符串类型,但C语言提供了字符串常量。
- C语言存在字符串的概念:它是一串以 NUL字节结尾的零个或多个字符。
- 字符串通常存储在字符数组中,这也是C语言没有显式的字符串类型的原因。
- 由于NUL字节是用于终结字符串的,所以在字符串内部不能有NUL字节,但是,这个限制一般不会造成问题。
- 之所以选择NUL作为字符串的终止符,是因为它不是一个可打印的字符。
- 字符串常量的书写方式是用一对双引号包围一串字符。字符串常量(不像字符常量)可以是空的。即使是空字符串,依然存在作为终止符的NUL字节。
K&RC:
在字符串常量的存储形式中,所有的字符和NUL终止符都存储于内存的某个位置。K&R C并没有提及一个字符串常量中的字符是否可以被程序修改,但它表明具有相同的值的不同字符串常量在内存中是分开存储的。因此,许多编译器都允许程序修改字符串常量。
ANSI C声明如果对一个字符串常量进行修改,其效果是未定义的。它也允许编译器把一个字符串常量存储于一个地方,即使它在程序中多次出现。这就使得修改字符串常量变得危险,因为对一个常量进行修改可能涉及程序中其他字符串常量。
因此,许多ANSI编译器不允许修改字符串常量,或者提供编译时选项,让你自行选择是否修改字符串常量。在实践中,需要避免,如果需要修改宇符串就把它存储于数组中。
- 把字符申常量和指针放在一起讨论是因为在程序中使用字符串常量会生成一个“指向字符的常量指针”,当一个字符串常量出现于一个表达式中时,表达式所使用的值就是这些字符所存储的地址,而不是这些字符本身。
- 因此,你可以把字符串常量赋值给一个“指向字符的指针”,后者指向这些字符所存储的地址。但是,你不能把字符串常量赋值给一个字符数组,因为字符串常量的直接值是一个指针,而不是这些字符本身。
参考《C和指针》