现在的位置: 首页 > 综合 > 正文

《c和指针》笔记

2018年05月27日 ⁄ 综合 ⁄ 共 3082字 ⁄ 字号 评论关闭

第6章 指针

未初始化和非法的指针

        如果变量是静态的,它会被初始化为0;但如果变量是自动的,它根本不会被初始化。无论是哪种情况,声明一个指向整型 的指针都不会“创建”用于存储整型值的内存空间。

        在对指针进行间接访问之前必须确保它们已被初始化!

NULL指针

        它作为一个特殊的指针变量,表示不指向任何东西。要使一个指针变量为NULL,可以给它赋一个零值。为了测试一个指针是否是NULL,可以将它与零值进行比较。

指针、间接访问和左值

        指针可以作为左值,因为它们是变量。对指针变量进行间接访问表示我们应该访问指针所指向的位置。间接访问指定了一个特定的内存位置,这样我们可以把间接访问表达式的结果作为左值使用。

指针、间接访问和变量

        &操作符产生变量a的地址,*操作符访问其操作数所表示的地址。

指针的指针

        双重间接访问**p

指针表达式

 

指针运算

        算术运算

                指针 +/-  整数   标准定义这种形式只能用于指向数组中某个元素的指针。偏移地址 = 整数 * 指针变量类型

                指针 - 指针        只有当两个指针都指向同一数组元素时,才允许从一个指针减去另一个指针,两个指针相减的值是两个指针在内存中的距离。(以数组元素的长度为单位)

        关系运算符

        <   <=   >   >=

                对指针执行关系运算也是有限制的,前提是它们都指向同一数组中的元素。

 

总结:计算机内存中的每一个位置都由一个地址标识。通常临近的内存位置合成一组,这样就允许存储更大的范围。指针就是它的值表示内存地址的变量。

        指针变量的值并非它所指向的内存位置所存储的值。我们必须用间接访问来获得它所指向位置存储的值。对一个“指向整型的指针”施加间接访问操作的结果将是一个整型值。

        声明一个指针变量并不会自动分配任何内存。在对指针执行间接访问之前,指针必须进行初始化:或者使它指向现有内存,或者给它分配动态内存。

        空指针就是不指向任何东西的指针。它可以赋值给一个指针,用于表示那个指针不指向任何值。

        指针变量也可以作为左值使用。对指针执行间接访问操作所产生的值也是个左值,标识一个特定的内存位置。

        极少情况下,偶尔需要使用指针常量,可以通过把一个整型值强制转换为指针类型来创建它。

        在指针值上可以执行一些有限的算术运算。指针运算只有作用于数组中其结果才能预测。如果一个指针减去一个整数后,运算结果产生的指针所指向的位置在数组第一个元素之前,那么它也是非法的。加法运算,如果结果指针指向数组最后一个元素后面的那个内存位置仍是合法的(但不能对这个指针执行间接访问操作),不过再往后就不合法了。

        任何指针之间都可以进行比较,测试他们相等或不相等。如果两个指针都指向同一数组中的元素,那么它们之间还可以执行关系运算,判断他们在数组中的位置。

 

第8章 数组

        在C中,在几乎所有使用数组名的表达式中,数组名的值是一个指针常量,也就是数组第1个元素的地址。它的类型取决于数组元素的类型,数组名的类型就是指向某类型的常量指针。

        数组具有一些和指针完全不同的特征:

                数组具有确定数量的元素,而指针只是一个标量值。编译器用数组名来记住这些属性,只有当数组名在表达式中使用时,编译器才会为它产生一个指针常量。

        指针常量所指向的是内存中数组的起始位置,不能修改常量的值。

        只有两种情况,数组名并不用指针常量来表示。当数组名作为sizeof或&的操作数时,sizeof返回整个数组的长度,取一个数组名的地址产生的是一个指向数组的指针。

        指针比下标更有效率,前提是它们被正确使用。

       

        指针和数组并不是相等的。它们都具有指针值,它们都可以进行间接访问和下标引用。但是它们还是存在相当大的区别。

                声明一个数组时,编译器将根据声明所指定的元素数量为数组保留内存空间,然后再创建数组名,它的值是一个常量,指向这段空间的起始位置。

                声明一个指针变量时,编译器只为指针本身保留内存空间,它并不为任何整型值分配内存空间。而且,指针变量并未被初始化为指向任何现有的内存空间,如果它是一个自动变量,它甚至根本不会被初始化。

        数组名的值就是一个指向数组第1个元素的指针。

 

数组总结:

        在绝大多数表达式中,数组名的值是指向数组第一个元素的指针。这个规则只有两个例外。sizeof返回整个数组所占用的字节而不是一个指针所占用的字节。单目操作符&返回一个指向数组的指针,而不是一个指向数组第一个元素的指针的指针。

        除了优先级不同之外,下标表达式array[value]和间接访问表达式*(array+(value))是一样的。因此,下标不仅可以用于数组名,也可以用于指针表达式中。指针表达式可能比下标表达式效率更高,但下标表达式绝对不可能比指针表达式效率更高。

        指针和数组并不相等。声明一个数组时,它同事分配了一些内存空间,用于容纳数组元素。声明一个指针时,它只分配了用于容纳指针本身的空间。

        当数组名作为函数参数传递时,实际传递给函数的是一个指向数组第一个元素的指针。函数所接收到的参数实际上是原参数的一份拷贝,所以函数可以对其进行操纵而不会影响实际的参数。但是,对指针参数执行间接访问操作允许函数修改原先的数组元素。数组形参可以声明为数组,也可以声明为指针。这两种声明形式只有当它们作为函数的形参时才是相等的。

        数组也可以用初始值列表进行初始化,初始值列表就是由一对花括号包围的一组值。静态变量在程序载入到内存时得到初始值。自动变量每次当执行流进如它们声明所在的代码时,都要使用隐式的赋值语句重新进行初始化。如果初始化列表的值的个数少于数组元素的个数,数组最后几个元素就用缺省值进行初始化。如果一个被初始化的数组的长度在声明中未给出,编译器将使这个数组的长度设置为刚好能容纳初始值列表中所有值的长度。字符数组也可以用一种很像字符串常量的快速方法进行初始化。

        多维数组实际上是一维数组的一种特型,就是它的每个元素本身也是一个数组。多维数组中的元素根据行主序进行存储,也就是右边下标率先变化。多维数组的值是一个指向它第一个元素的指针。也就是一个指向数组的指针。对该指针进行运算将根据它所指向数组的长度对操作数进行调整。多维数组的下标引用也是指针表达式。当一个多维数组作为参数传递给一个函数时,它所对应的函数形参的声明中必须显式的知名第二维的长度。由于多维数组实际上是复杂元素的一维数组,一个多维数组的初始化列表就包含了这些复杂元素的值。这些值的每一个都可能包含嵌套的初始值列表,由数组各维长度决定。如果多维数组的初始化列表是完整的,它的内层花括号可以省略。在多维数组的初始化值列表中,只有第一维的长度会被自动计算出来。

        传建指针数组,字符串的列表可以以矩阵的形式存储,也可以以指向字符串常量的指针数组形式存储。在矩阵中,每行必须与最长字符串的长度一样长,单它不需要人和指针。指针数组本身要占用空间,但每个指针所指向的字符串所占用的内存空间就是字符串本身的长度。

抱歉!评论已关闭.