数组和指针
关键字
static
运算符
&
*
(一元)创建和初始化数组
指针、指针和数组
处理数组的函数
二维数组
数组
C99 标准中的新特性:指定初始化器(designated initializer),可以初始化指定的元素。
未初始化的都为 0.
C 语言的数组要注意边界,数组越界也是一个数组使用的常见问题。
二维数组。
指针和数组
指针提供了一种用符号使用地址的方法。计算机硬件指令依赖地址,指针把程序员的想法以更接近机器的方式传递给机器
指针的值是它指向的地址。许多计算机按字节编址,一个 int 类型的地址通常是第一个字节的地址
指针前面使用
*
可以得到指向对象的值指针加 1,指针的值递增指向类型的大小
上例说明数组和指针关系密切。
指针和数组的区别
指针存放地址变量,可以修改
数组是存储多个元素的集合。数组名本身可以用作指向数组首元素的指针,但数组本质上是一个固定大小的内存块。
函数、数组和指针
C 语言函数处理数组是本质上传入的是指针,所以通常要有一个额外的参数指明数组长度
注意第一个参数是指针形参。还有另一种操作方法
指针变量的基本操作
复制
解引用 ,即
*ptr
计算出指向地址的值取地址,指针存放的地址
指针与整数相加,如
ptr + 2
,先用整数和指向类型大小相乘,然后与初始地址相加指针递增,移动到下一元素,本质和加整数一样
指针求差
ptr1 - ptr2
,计算同一数组两元素的距离
数组中数据的保护
通常处理数组时,传递地址的问题:会对数据产生修改。有时候我们并不会修改数组数据,只读。更好的做法:
const
告诉编译器,函数不可以修改此指针指向的内容。
关于 const,如果定义一个常量
还有一个要注意的
关于 const
的讨论
指针和多维数组
matrix 是该数组首元素的地址。matrix 的首元素 matrix[0]
是一个包含两个 int 的数组。
matrix == &matrix[0], &matrix[0] == &matrix[0][0]
matrix[0] 是一个地址,地址指向的类型为一个 int
matrix 也是一个地址,地址指向的类型为 2*int
matrix[0] + 1,和 matrix + 1 指向的地址不一样,参考上一条与指针整数相加
指针的解引用
*(matrix[0]) 的值为 matrix[0][0]
*matrix 的值为 &matrix[0][0]
**matrix 和 *&matrix[0][0] 等价
matrix 是地址的地址,是指针的指针,需要解引用两次才得到值。双重间接(double indirection)
一个等价的表示 *(*(matrix+2) + 1)
和 matrix[2][1]
如果想声明一个指针,指向一个二维数组,比如指向 matrix,int *ptr 是不行的,ptr 指向的是一个整数类型,和 matrix[0] 的类型匹配。matrix 是一个含有两个 int 类型的一维数组。因此指针要为指向一个内含两个int的数组
int:这是基本数据类型,表示整数。(*pz):这是一个指针的声明,指针 pz 会被解引用。[2]:这是一个数组的大小,表示数组中有 2 个元素。
综合起来,int (*pz)[2] 就是一个指向包含 2 个整数的数组的指针。这种指针通常用于传递数组到函数中,而不仅仅是单个整数或指向整数的指针。
指针之间的赋值比较严格。不像变量之间赋值,int 可以直接赋值为 double
函数和多维数组
向函数传入一个多维数组这个需求是很常见的。
含义为 ptr 是个指针,指向包含4个int元素的对象。
特别要注意的是
这个语法是不对的,。编译器会把数组表示法转换成指针表示法,如 ptr[1] 转换成 *(ptr + 1),对 ptr + 1 求值,需要知道 ptr 指向的对象的大小(指针和整数的运算),因此上面的声明直接就是有问题的。
这个声明是没问题的,也是最好理解的,但事实上,有没有3 无所谓,甚至 3 是被编译器忽略的。
加深理解
进一步地,声明一个指向 N 维数组的指针时,只省略最左边的值
原理同上,第一对方括号指明是个指针,后面的描述指针指向数据的类型。
变长数组 VLA
对于数组处理函数的声明
对于二维数组处理函数的声明
只把行数作为了函数形参,列数内置在函数体内了。
如何向使用一个函数处理任意行列的数组,一个做法是把数组作为一维数组传递,同时传入行列值,函数内计算每行的开始。
字面量
5 是 int 类型的字面量,'a' 是 char 类型的字面量,"hello world" 是字符串字面量。数组的字面量
字面量需要在创建的时候就使用。
对于二维数组字面量也是类似的
最后更新于