如何建立公司网站账号wordpress 简约企业
一维数组
在 C 语言里,一维数组指针指的是指向一维数组的指针。它和普通指针不同,普通指针指向单个变量,而一维数组指针指向的是一整个一维数组。一维数组指针存储的是数组的起始地址,并且它的类型和所指向的数组类型相匹配。
声明与初始化
声明一维数组指针的一般格式为:
数据类型 (*指针变量名)[数组长度];
这里的括号不能省略,因为[]
的优先级比*
高,若不使用括号,声明的就会是一个指针数组。下面是具体的声明和初始化示例:
#include <stdio.h>int main() {int arr[5] = {1, 2, 3, 4, 5};int (*ptr)[5] = &arr; // 声明并初始化一个指向包含5个int元素的数组的指针return 0;
}
在上述代码中,ptr
是一个指向包含 5 个 int
类型元素的数组的指针,通过 &arr
把数组 arr
的地址赋给了 ptr
。
数组本质上不是一个指针,我们可以通过sizeof进行查看
#include "stdio.h"
#include "stdlib.h"
#include "string.h"void array_test01() {int array[5] = {1,2,3,4,5};//一维数组是不是指针?printf("array siof: %d\n",sizeof(array));
}int main() {array_test01();return EXIT_SUCCESS;
}
运行结果
数组赋值给指针
我们看以下案例:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"void array_test01() {int array[5] = {1,2,3,4,5};int* p = NULL;p = &array;printf("array index: %d\n", *(p+0));
}int main() {array_test01();return EXIT_SUCCESS;
}
运行结果
从提示来看,两者赋值是不支持的。两者的的指针其实不是一个等价指针,可以看下面警告,间接级别不同。原因是两者之间的步长并不是等价。
数组的步长
void array_test02() {int array[5] = { 1,2,3,4,5 };printf("array index: %d\n",&array);printf("array index: %d\n",&array + 1);
}int main() {array_test02();return EXIT_SUCCESS;
}
从&array+1后直接就跳转到了最后一位的地址。如果是数组取地址的话,取的是整个数组的指针,直接跳转,会跳转到最后
向以下案例就属于等价的。
#include "stdio.h"
#include "stdlib.h"
#include "string.h"void array_test01() {int array[5] = {1,2,3,4,5};int* p = array;printf("array index: %d\n", *(p+0));
}int main() {array_test01();return EXIT_SUCCESS;
}
指针常量
指针的指向是不可修改的,但是可以修改指针内部元素
指针放负数,原理
我们的数组是可以放入负数的。
#include "stdio.h"
#include "stdlib.h"
#include "string.h"void array_test01() {int array[5] = {1,2,3,4,5};int* p = array;p = p + 3;printf("array: %d\n", p[-1]);
}int main() {array_test01();return EXIT_SUCCESS;
}
运行结果
逻辑
首先当前p的偏移位置在第3位,然后,p[-1] 就是第2 。 其实是等价的
定义一个数组的指针
方式1
直接通过数组赋地址给指针,对数组名称取地址,获取的是指针步长,是整个数组的长
void array_test01() {int array[5] = {1,2,3,4,5};int* p = &array; //这种方式并不是数组指针,对数组名称取地址,获取的是指针步长,是整个数组的长度
}
如果需要定义一个数组指针,首先定义出数组的类型,在通过类型创建数组的指针。
void array_test01() {int array[5] = {1,2,3,4,5};typedef int(ARRAY_TYPE)[5]; //ARRAY_TYPE是一个数据类型,代表有5个int类型的数组元素ARRAY_TYPE *p = &array;for (int i = 0; i < 5;i++) {//首先是p的地址,如果不把p解引用,那会打印的是地址printf("%d\n",(*p)[i]);}
}
方式2
先定义数组指针的类型,在创建数组指针的变量
void array_test01() {int array[5] = {1,2,3,4,5};typedef int(*ARRAY_TYPE)[5]; //先定义数组指针的类型,在创建数组指针的变量ARRAY_TYPE p = &array;for (int i = 0; i < 5;i++) {//首先是p的地址,如果不把p解引用,那会打印的是地址printf("%d\n",(*p)[i]);}
}
与上面方法有所不同,定义规则直接就变了,直接一步到位。
方式3
直接创建数组指针变量
void array_test01() {int array[5] = {1,2,3,4,5};int (*p)[5] = &array; // 直接创建数组指针变量for (int i = 0; i < 5;i++) {//首先是p的地址,如果不把p解引用,那会打印的是地址printf("%d\n",(*p)[i]);}
}
案例
案例1
#include "stdio.h"
#include "stdlib.h"
#include "string.h"void printf_array(int arr[],int len) {// int arr[],等价与int * arrfor (int i = 0; i < len; i++) {printf("%d\n",arr[i]); //给人看//printf("%d\n",*(arr+i));//给机器看}
}void array_test01() {int array[5] = {1,2,3,4,5};int arr_len = sizeof(array) / sizeof(array[0]);printf_array(array,arr_len);
}int main() {array_test01();return EXIT_SUCCESS;
}
案例2
借助数组指针,可以通过偏移和间接引用操作符来访问数组元素。
#include <stdio.h>int main() {int arr[5] = {1, 2, 3, 4, 5};int (*ptr)[5] = &arr;// 访问数组的第三个元素printf("数组的第三个元素是: %d\n", (*ptr)[2]);return 0;
}
在这个例子中,(*ptr)
先对指针 ptr
进行解引用,得到数组本身,然后 [2]
访问数组的第三个元素(下标从 0 开始)。
案例3
一维数组指针能够作为函数参数传递,这样可以在函数内部对数组进行操作。
#include <stdio.h>// 函数接收一个指向包含5个int元素的数组的指针
void printArray(int (*ptr)[5]) {for (int i = 0; i < 5; i++) {printf("%d ", (*ptr)[i]);}printf("\n");
}int main() {int arr[5] = {1, 2, 3, 4, 5};int (*ptr)[5] = &arr;printArray(ptr);return 0;
}
在上述代码中,printArray
函数接收一个指向包含 5 个 int
元素的数组的指针作为参数,在函数内部通过该指针访问数组元素并打印。
案例4
在处理二维数组时,可利用一维数组指针来遍历二维数组的每一行。
#include <stdio.h>int main() {int arr[3][4] = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}};// 声明一个指向包含4个int元素的数组的指针int (*ptr)[4];for (ptr = arr; ptr < arr + 3; ptr++) {for (int i = 0; i < 4; i++) {printf("%d ", (*ptr)[i]);}printf("\n");}return 0;
}
在这个例子中,ptr
是一个指向包含 4 个 int
元素的数组的指针。外层循环让 ptr
依次指向二维数组的每一行,内层循环遍历当前行的每个元素。
二维数组
在 C 语言中,二维数组指针是指向二维数组的指针。二维数组在内存中是按行优先的顺序连续存储的,二维数组指针可以用来指向这个连续的内存块,并且可以方便地对二维数组进行操作。
从本质上来说,二维数组指针指向的是二维数组的一行,它存储的是二维数组某一行的起始地址
声明二维数组指针
声明二维数组指针的一般形式为:
数据类型 (*指针变量名)[列数];
这里的括号是必需的,因为[]
的优先级高于*
,不加括号就会声明成指针数组。例如,声明一个指向包含 3 个int
类型元素的数组的指针:
int (*ptr)[3];
定义二维数组
#include "stdio.h"
#include "stdlib.h"
#include "string.h"void array_test01() {//格式1int array1[3][3] = { {1,2,3},{4,5,6},{7,8,9}};//格式2int array2[3][3] = {1,2,3,4,5,6,7,8,9};//格式3int array3[][3] = {1,2,3,4,5,6,7,8,9};
}int main() {array_test01();return EXIT_SUCCESS;
}
二维数组指针
#include "stdio.h"
#include "stdlib.h"
#include "string.h"void array_test01() {int array[3][3] = { {1,2,3},{4,5,6},{7,8,9}};int (*p)[3] = array; //二维数组名称 指向 第一个一维数组的指针//特殊情况printf("sizeof: %d",sizeof(array)); //9个 int类型,输出36//创建二维数组指针int (*p2)[3][3] = &array;}int main() {array_test01();return EXIT_SUCCESS;
}
指向二维数组并访问元素
#include <stdio.h>int main() {int arr[2][3] = {{1, 2, 3},{4, 5, 6}};// 声明并初始化二维数组指针int (*ptr)[3] = arr; // 访问第一行第二列的元素printf("第一行第二列的元素: %d\n", ptr[0][1]);// 另一种访问方式printf("第一行第二列的元素: %d\n", *(*(ptr + 0) + 1));return 0;
}
解释:
int (*ptr)[3] = arr;
:这里arr
代表二维数组首行的地址,将其赋值给ptr
,ptr
就指向了二维数组的第一行。ptr[0][1]
:ptr[0]
表示第一行的首地址,再加上偏移量1
就访问到第一行第二列的元素。*(*(ptr + 0) + 1)
:ptr + 0
指向第一行,*(ptr + 0)
得到第一行首地址,*(ptr + 0) + 1
得到第一行第二列元素的地址,最后再解引用就得到该元素的值。
二维数组输出
#include "stdio.h"
#include "stdlib.h"
#include "string.h"//以下三种方式都是等价的
//void arrayPrintf(int arr[3][3],int row,int col) {
//void arrayPrintf(int arr[][3],int row,int col) {
void arrayPrintf(int (*arr)[3], int row, int col) {for (size_t i = 0; i < row; i++){for (size_t j = 0; j < col; j++){//printf("%d ",arr[i][j]); //给人看printf("%d ",*(*(arr + i)+j)); //机器看}printf("\n");}
}void array_test01() {int array[3][3] = { {1,2,3},{4,5,6},{7,8,9}};arrayPrintf(array, 3, 3);
}int main() {array_test01();return EXIT_SUCCESS;
}
输出结果
动态分配二维数组并使用指针操作
#include <stdio.h>
#include <stdlib.h>int main() {int rows = 2;int cols = 3;// 动态分配二维数组int (*arr)[3] = (int (*)[3])malloc(rows * sizeof(*arr));if (arr == NULL) {printf("内存分配失败\n");return 1;}// 初始化二维数组for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {arr[i][j] = i * cols + j;}}// 打印二维数组for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {printf("%d ", arr[i][j]);}printf("\n");}// 释放内存free(arr);return 0;
}
int (*arr)[3] = (int (*)[3])malloc(rows * sizeof(*arr));
:使用malloc
函数动态分配了一个包含rows
行、cols
列的二维数组。sizeof(*arr)
表示一行的大小。- 之后通过双重循环对二维数组进行初始化和打印操作。
- 最后使用
free(arr)
释放动态分配的内存,避免内存泄漏。