再战指针!(C Primer Plus 第六版基础整合)(三)

简介: 再战指针!(C Primer Plus 第六版基础整合)(三)

八、保护数组中的数据



编写一个处理基本类型(如, int)的函数时,要选择是传递int类型的值还是传递指向int的指针。通常都是直接传递数值,只有程序需要在函数中改变该数值时,才会传递指针。对于数组别无选择,必须传递指针,因为这样做效率高。如果一个函数按值传递数组,则必须分配足够的空间来储存原数组的副本,然后把原数组所有的数据拷贝至新的数组中。如果把数组的地址传递给函数,让函数直接处理原数组则效率要高。


传递地址会导致一些问题。C通常都按值传递数据,因为这样做可以保证数据的完整性。如果函数使用的是原始数据的副本,就不会意外修改原始数据。但是,处理数组的函数通常都需要使用原始数据,因此这样的函数可以修改原数组。


对形参使用const

在K&R C的年代,避免类似错误的唯一方法是提高警惕。ANSI C提供了一种预防手段。如果函数的意图不是修改数组中的数据内容,那么在函数原型和函数定义中声明形式参数时应使用关键字 const。例如,sum ( )函数的原型和定义如下:


以上代码中的const告诉编译器,该函数不能修改ar指向的数组中的内容。如果在函数中不小心使用类似ar [ i]++的表达式,编译器会捕获这个错误,并生成一条错误信息。

这里一定要理解,**这样使用const并不是要求原数组是常量,而是该函数在处理数组时将其视为常量,不可更改。这样使用const可以保护数组的数据不被修改,就像按值传递可以保护基本数据类型的原始值不被改变一样。**一般而言,如果编写的函数需要修改数组,在声明数组形参时则不使用const:如果编写的函数不用修改数组,那么在声明数组形参时最好使用const。


九、指针和多维数组的关系



书上写的也很详细


b站有个视频写的也挺好,分享出来


https://www.bilibili.com/video/BV1MJ411D7EX


下面这个是我做的笔记(下次一定把字写好)


image.png


此时,C和C[0]的值都是二维数组的首地址


实例


#include <stdio.h>
int main(void)
{
    int zippo[4][2] = {{2, 4}, {6, 8}, {1, 3}, {5, 7}};
    //zippon 拉链
    printf("zippo = %p,zippo + 1 = %p\n", zippo, zippo + 1);            //zippo和zippo[0]都是二维数组的首地址
    printf("zippo[0] = %p, zippo[0]+1 = %p\n", zippo[0], zippo[0] + 1); //zippo+1是指向第二个一维数组,zippo[0]+1是第一个一维数组的第二个元素
    printf("*zippo = %p,*zippo+1 = %p\n", *zippo, *zippo + 1);
    printf("zippo[0][0] = %d\n", zippo[0][0]);
    printf("*zippo[0] = %d\n", *zippo[0]);
    printf("**zippo = %d \n", **zippo);
    printf("zippon[2][1] = %d\n", zippo[2][1]);
    printf("*(*(zippo+2)+1) = %d\n", *(*(zippo + 2) + 1));
    return 0;
}
输出的结果:
PS D:\Code\C\指针> cd "d:\Code\C\指针\" ; if ($?) { gcc 指针Demo06.c -o 指针Demo06 } ; if ($?) { .\指针Demo06 }
zippo = 000000000061FE00,zippo + 1 = 000000000061FE08
zippo[0] = 000000000061FE00, zippo[0]+1 = 000000000061FE04
*zippo = 000000000061FE00,*zippo+1 = 000000000061FE04
zippo[0][0] = 2
*zippo[0] = 2
**zippo = 2
zippon[2][1] = 3
*(*(zippo+2)+1) = 3


解析


其他系统显示的地址值和地址形式可能不同,但是地址之间的关系与以上输出相同。该输出显示了二维数组zippo的地址和一维数组zippo[0]的地址相同。它们的地址都是各自数组首元素的地址,因而与&zippo [0] [0]的值也相同。


尽管如此,它们也有差别。在我们的系统中, int是4字节。前面讨论过,zippo[0]指向一个4字节的数据对象。zippo[0]加1,其值加4。


数组名zippo 是一个内含2个int类型值的数组的地址,所以zippo指向一个8字节的数据对象。因此,zippo 加1,它所指向的地址加8字节。


该程序演示了zippo[0]和zippo完全相同,实际上确实如此。然后,对二维数组名解引用两次,得到储存在数组中的值。使用两个间接运算符(*)或者使用两对方括号([])都能获得该值(还可以使用一个和一对[ ],但是我们暂不讨论这么多情况)。


要特别注意,与 zippo[2] [1]等价的指针表示法是 ((zippo+2) + 1)。看上去比较复杂,应最好能理解。下面列出了理解该表达式的思路:


zippo 二维数组首元素的地址(每个元素都是内含两个int类型元素的一维数组)


zippo + 2 二维数组的第三个一维数组的地址


*(zippo + 2)二维数组的第三个一维数组的地址首元素(一个int类型的值)地址


*(zippo + 2)+ 1 二维数组的第3个元素(即一维数组)的第2个元素(也是一个int类型的值)地址


*(*(zippo + 2)+ 1) 二维数组的第3个元素(即一维数组)的第2个元素的值,即zippo[2][1]


以上分析并不是为了说明用指针表示法(* (*(zippo+2) + 1))代替数组表示法(zippo[2][1]),而是提示读者,如果程序恰巧使用一个指向二维数组的指针,而且要通过该指针获取值时,最好用简单的数组表示法,而不是指针表示法。


十、总结



数组是一组数据类型相同的元素。数组元素按顺序储存在内存中,通过整数下标(或索引)可以访问各元素。在c中,数组首元素的下标是0,所以对于内含n 个元素的数组,其最后一个元素的下标是n-1。作为程序员,要确保使用有效的数组下标,因为编译器和运行的程序都不会检查下标的有效性。


把数组名解释为该数组首元素的地址。换言之,数组名与指向该数组首元素的指针等价。概括地说,数组和指针的关系十分密切。如果ar是一个数组,那么表达式ar[i]和 (ar+i)等价。*


二维数组即是数组的数组。例如,下面声明了一个二维数组:


double sales [5] [12] ;


该数组名为sales,有5个元素(一维数组),每个元素都是一个内含12个double类型值的数组。第1个一维数组是sales [0],第2个一维数组是sales [1],以此类推,每个元素都是内含12个double类型值的数组。使用第2个下标可以访问这些一维数组中的特定元素。例如,sales [2] [5]是slaes[2]的第6个元素,而sales [ 2]是sales的第3个元素。


十一、复习题


image.png

image.png

image.png


相关文章
|
6月前
|
编译器 vr&ar C语言
C primer plus 学习笔记 第10章 数组和指针
C primer plus 学习笔记 第10章 数组和指针
|
7月前
|
C++
来自C++ Primer 5的函数指针的定义,调用等
来自C++ Primer 5的函数指针的定义,调用等
42 0
指向结构指针(C Primer Plus 第六版)
指向结构指针(C Primer Plus 第六版)
79 0
指针和多维数组的关系(C Primer Plus第六版)
指针和多维数组的关系(C Primer Plus第六版)
65 0
|
C语言
指针常用的操作(C Primer Plus第六版)
指针常用的操作(C Primer Plus第六版)
110 0
|
索引
指针如何使用形参?(C Primer Plus第六版)
指针如何使用形参?(C Primer Plus第六版)
81 0
|
28天前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
100 13
|
2月前
|
C语言
无头链表二级指针方式实现(C语言描述)
本文介绍了如何在C语言中使用二级指针实现无头链表,并提供了创建节点、插入、删除、查找、销毁链表等操作的函数实现,以及一个示例程序来演示这些操作。
35 0
|
3月前
|
存储 人工智能 C语言
C语言程序设计核心详解 第八章 指针超详细讲解_指针变量_二维数组指针_指向字符串指针
本文详细讲解了C语言中的指针,包括指针变量的定义与引用、指向数组及字符串的指针变量等。首先介绍了指针变量的基本概念和定义格式,随后通过多个示例展示了如何使用指针变量来操作普通变量、数组和字符串。文章还深入探讨了指向函数的指针变量以及指针数组的概念,并解释了空指针的意义和使用场景。通过丰富的代码示例和图形化展示,帮助读者更好地理解和掌握C语言中的指针知识。
122 4
|
4月前
|
C语言
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)