C语言之数组指针指针数组

Posted 流楚丶格念

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言之数组指针指针数组相关的知识,希望对你有一定的参考价值。

数组和指针

问题导引

指针和数组并不是相等的。为了说明这个概念,请考虑下面两个声明:

int a[10];
int *b;

声明一个数组时,编译器根据声明所指定的元素数量为数组分配内存空间,然后再创建数组名,指向这段空间的起始位置。声明一个指针变量的时候,编译器只为指针本身分配内存空间,并不为任何整型值分配内存空间,指针并未初始化指向任何现有的内存空间。

因此,表达式*a是完全合法的,但是表达式*b却是非法的。*b将访问内存中一个不确定的位置,将会导致程序终止。另外,如果是b++的话是可以通过编译的,而a++却不行,因为a是一个常量值。

b++;	// 可以
a++;	// 报错

作为函数参数的数组名

当一个数组名作为一个参数传递给一个函数的时候发生什么情况呢?我们现在知道数组名其实就是一个指向数组第1个元素的指针,所以很明白此时传递给函数的是一份指针的拷贝。所以函数的形参实际上是一个指针。

此时,系统也会对指针进行拷贝,然后进行一系列函数操作,当对数据操作的时候,指针指向的仍然是原数据,操作的仍是原数据本身,所以这里的即使对指针拷贝也是当做实际参数。

但是为了使程序员新手容易上手一些,编译器也接受数组形式的函数形参。因此下面两种函数原型是相等的:

int print_array(int *arr);
int print_array(int arr[]);

问题1:我们可以使用任何一种声明,但哪一个更准确一些呢?

答案是指针形式。因为实参实际上是个指针,而不是数组。同样sizeof arr值是指针的长度,而不是数组的长度。

现在我们清楚了,为什么一维数组中无须写明它的元素数目了,因为形参只是一个指针,并不需要为数组参数分配内存。另一方面,这种方式使得函数无法知道数组的长度。如果函数需要知道数组的长度,它必须显式传递一个长度参数给函数。

代码上看指针数组与数组指针

int* a[4]     指针数组     
  • 表示:数组a中的元素都为int型指针

  • 元素表示:*a[i]*(a[i])是一样的,因为[]优先级高于*

int (*a)[4]   数组指针     
  • 表示:指向数组a的指针

  • 元素表示:(*a)[i]

从代码声明中看的出来,他们俩只有一个括号的区分,那么下面我们来具体说明一下:

数组指针:指向数组的指针

数组指针,它是指针,指向数组的指针。

它是指针,它是指针,它是指针。重要的事情说三遍。

数组的类型由元素类型和数组大小共同决定,例如:int array[5] 的类型为 int[5]

数组指针的定义

C语言可通过typedef定义一个数组类型:
定义数组指针有一下三种方式:

方式一

void test01(){

	//先定义数组类型,再用数组类型定义数组指针
	int arr[10] = {1,2,3,4,5,6,7,8,9,10};
	//有typedef是定义类型,没有则是定义变量,下面代码定义了一个数组类型ArrayType
	typedef int(ArrayType)[10];
	//int ArrayType[10]; //定义一个数组,数组名为ArrayType

	ArrayType myarr; //等价于 int myarr[10];
	ArrayType* pArr = &arr; //定义了一个数组指针pArr,并且指针指向数组arr
	for (int i = 0; i < 10;i++){
		printf("%d ",(*pArr)[i]);
	}
	printf("\\n");
}

方式二

void test02(){

	int arr[10];
	//定义数组指针类型
	typedef int(*ArrayType)[10];
	ArrayType pArr = &arr; //定义了一个数组指针pArr,并且指针指向数组arr
	for (int i = 0; i < 10; i++){
		(*pArr)[i] = i + 1;
	}
	for (int i = 0; i < 10; i++){
		printf("%d ", (*pArr)[i]);
	}
	printf("\\n");

}

方式三

void test03(){
	
	int arr[10];
	int(*pArr)[10] = &arr;

	for (int i = 0; i < 10; i++){
		(*pArr)[i] = i + 1;

	}
	for (int i = 0; i < 10; i++){
		printf("%d ", (*pArr)[i]);
	}
	printf("\\n");
}

输出:

指针数组:数组元素为指针

指针数组,它是数组,数组中的元素为指针。

其实就是我们熟知的存数据的数组。

他又分两种:栈区指针数组(系统自动分配空间)与堆区指针数组(程序员通过malloc new分配空间)

栈区指针数组

不申请内存空间:

#include<stdio.h>
#include<string.h>

// 数组做函数函数,退化为指针
void array_sort(char** arr, int len) {

	for (int i = 0; i < len; i++) {
		for (int j = len - 1; j > i; j--) {
			//比较两个字符串
			if (strcmp(arr[j - 1], arr[j]) > 0) {
				char* temp = arr[j - 1];
				arr[j - 1] = arr[j];
				arr[j] = temp;
			}
		}
	}

}

// 打印数组
void array_print(char** arr, int len) {
	for (int i = 0; i < len; i++) {
		printf("%s\\n", arr[i]);
	}
	printf("--------------------------\\n");
}

void test() {

	//主调函数分配内存
	//指针数组
	char* p[] = { "bbb", "aaa", "ccc", "eee", "ddd" };
	//char** p = { "aaa", "bbb", "ccc", "ddd", "eee" }; //错误
	int len = sizeof(p) / sizeof(char*);
	//打印数组
	printf("排序前:\\n");
	array_print(p, len);
	//对字符串进行排序
	array_sort(p, len);
	//打印数组
	printf("排序后:\\n");
	array_print(p, len);
}

int main()
{
	test();
	return 0;
}

运行结果:

堆区指针数组

动态申请内存空间:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//分配内存
char** allocate_memory(int n) {

	if (n < 0) {
		return NULL;
	}

	char** temp = (char**)malloc(sizeof(char*) * n);
	if (temp == NULL) {
		return NULL;
	}

	//分别给每一个指针malloc分配内存
	for (int i = 0; i < n; i++) {
		temp[i] = (char *)malloc(sizeof(char) * 30);
		sprintf(temp[i], "%2d 大家好!", i + 1);
	}

	return temp;
}

//打印数组
void array_print(char** arr, int len) {
	for (int i = 0; i < len; i++) {
		printf("%s\\n", arr[i]);
	}
	printf("---------  打印完了  -------------\\n");
}

//释放内存
void free_memory(char** buf, int len) {
	if (buf == NULL) {
		return;
	}
	for (int i = 0; i < len; i++) {
		free(buf[i]);
		buf[i] = NULL;
	}

	free(buf);
}

void test() {

	int n = 10;
	char** p = allocate_memory(n);
	//打印数组
	array_print(p, n);
	//释放内存
	free_memory(p, n);
}

int main()
{
	test();
	return 0;
}

运行结果:

以上是关于C语言之数组指针指针数组的主要内容,如果未能解决你的问题,请参考以下文章

C之数组指针和指针数组(二十九)

c语言中如何通过二级指针来操作二维数组

C语言中数组与指针的异同之处!你不知道的编程奥秘~

C语言基础之指针入门

C语言复习之字符指针(迭代内存申请等操作)

C语言之指针学习