数组和指针

  • 关键字 static

  • 运算符 & * (一元)

  • 创建和初始化数组

  • 指针、指针和数组

  • 处理数组的函数

  • 二维数组

数组

C99 标准中的新特性:指定初始化器(designated initializer),可以初始化指定的元素。

int array[50] = {
    0,
    1,
    [20] = 20,
    21,
    [49] = 49,
};
int arr[5] = {1, 2, 3, 4, 5};

未初始化的都为 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" 是字符串字面量。数组的字面量

字面量需要在创建的时候就使用。

对于二维数组字面量也是类似的

最后更新于

这有帮助吗?