C语言学习

指针进阶

关于指针的部分基础概念:

  • 指针就是变量,用来存放地址,地址唯一标识一块内存空间。
  • 32位平台指针的大小固定为4个字节,64位平台固定为8个字节。
  • 指针是有类型,指针的类型决定了指针加减整数的步长,指针解引用操作的时候的权限。

这篇博客主要介绍指针数组数组指针传参
先看一段代码:

int main()
{
	char str1[] = "hello word";
	char str2[] = "hello word";
	const char* str3 = "hello word";
	const char* str4 = "hello word";
	if (str1 == str2)
		printf("str1 == str2"); 
	else
		printf("str1!=str2");  
	if (str3 == str4)
		printf("str3 == str4");  
	else
		printf("str3!=str4");
	return 0;
}
//输出结果为
//str1!=str2str3 == str4

这段代码展示了,基本类型变量str1str2在内存中单独开辟空间来存放hello word,而指针变量str3str4指向的是常量字符串,不能修改(如下面代码,将指针变量str4进行修改),因此在内存中只会存在一份。

int main()
{
	char str1[] = "hello word";
	char str2[] = "hello word";
	const char* str3 = "hello word";
	const char* str4 = "hello word";
	const char* str4 = "h";
	if (str1 == str2)
		printf("str1 == str2"); 
	else
		printf("str1!=str2");  
	if (str3 == str4)
		printf("str3 == str4");  
	else
		printf("str3!=str4");
	return 0;
}

修改指针变量str4的执行结果:
修改指针变量str4的执行结果

指针数组

指针数组本质上就是数组中存放的是指针也就是地址。如何使用,请看代码:

int main()
{
	int a = 5;
	int b = 5;
	int c = 5;
	int* arr[3] = { &a, &b, &c };  
	return 0;
}

通过int* e = &a; 可以创建指针变量,int* arr[3];表示创建存放整型指针的数组其中有3个元素(每个元素的类型是int*也就是整型指针)。再看一个例子,打印出三个数组中元素:

int main()
{
	int a[] = { 1, 2, 3, 4, 5 };
	int b[] = { 2, 3, 4, 5, 6 };
	int c[] = { 3, 4, 5, 6, 7 };
	int* arr[] = {a, b, c}; //数组名字就相当于数组首元素地址,相当于把abc数组首元素地址传给arr
	int i = 0;
	for (i = 0; i < 3;i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			//arr[i]是内存地址,加j表示地址加j,会跳到下一个元素的地址。
			printf("%d ",*(arr[i]+j));  
			//也可以这样子printf("%d ",arr[i][j]);  arr[i][j]相当于上面,[j]可以理解为+j再解引用
		}
	}
	return 0;
}

上述代码执行结果:
打印数组的元素

数组指针

数组指针,是指针中存放的是数组的地址。下面代码以int类型和double以及double*类型创建了数组指针。

int main()
{
	int arr[10] = { 1, 2, 3, 4, 5 };
	int(*pa)[10] = &arr; //去除数组的地址
	//parr就是数组指针-其中存放的是数组的地址
	double* d[5];      //数组中的每个元素是double*
	double* (*pd)[5] = &d;
	return 0;
}

int (*pa)[10] = &arr ;int表示数组的类型,*pa表示其是一个指针,[10]表示指针指向的是一个包含10个元素的数组。

数组指针和指针的区别

int main()
{
	int arr[10] = { 0 };
	//值一样,但是类型不一样
	printf("%p\n",arr);  //首元素地址  —— 操作长度不一致,可以打印加一看看结果
	//00F3FA90
	printf("%p\n",&arr); //数组的地址
	//00F3FA90
	printf("%p\n", arr + 1);
	//00F3FA94
	printf("%p\n", &arr + 1);
	//00F3FAB8
	//指针
	int* p = arr;   //指针指向首元素
	//数组指针
	int (*p2)[10] = &arr; //取数组的地址,首先(*p2)表示其是指针,[10]表示其指向为一个含有10个元素的数组,类型为int
	printf("%p\n", p);    
	//00F3FA90
	printf("%p\n", p+1);    //跳过一个元素的4个字节
	//00F3FA94
	printf("%p\n", p2);   
	//00F3FA90
	printf("%p\n", p2+1);   // 跳过整个数组
	//00F3FAB8
	return 0;
}

arr表示数组首元素的地址,&arr显示的是首元素地址但其表示整个数组地址,因此打印的一样,整型数组每个元素都是4个字节,因此arr+1其表示下一个元素的地址,因此是00F3FA90+4=00F3FA94(16进制)。整个数组有10个元素,每个元素是4个字节,&arr+1地址变化为00F3FA90+40=00F3FAB8int* p = arr;创建指针指向的是首元素地址,p+1之后地址变化为4个字节,int (*p2)[10] = &arr;表示数组指针p2+1会跳过整个数组和&arr一致。

数组名是数组首元素的地址的两个例外

  • sizeof(数组名)——数组名表示整个数组,计算的是整个数组大小,单位是字节。
  • &数组名——表示取出的是整个数组的地址。

数组指针的使用:
通过数组指针来打印一维数组中的元素:

int main()
{
	int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9,10};
	int i = 0;
	for (i = 0;i < 10;i++)
	{
		printf("%d ", *((*pa)+i)); 
		// *pa就相当于arr,pa是整个数组的地址,*pa对其解引用,
		// 表示拿到了整个数组相当于arr也就是首元素的地址,通常用于二维数组
	}
	return 0;
}

打印一维数组
数组指针并不常用来处理一维数组。

使用数组指针打印二维数组中的元素:

void print(int (*p)[5], int r, int c)   //数组指针接收,arr是第一个元素的地址,第一个元素是一个数组,因此接收的指针为数组指针,加1时可以直接跳过此数组,也就是直接跳过这一行
{
	int i = 0;
	int j = 0;
	for (i = 0;i < r;i++)
	{
		for (j = 0;j < c;j++)
		{
			printf("%d ", (*(p+i)+j)); 
		   // p存放的是数组地址,p+1之后,会直接跳过一个数组,到第二行,p+i解引用后指的是第i行的第一个元素
		}
		printf("\n");
	}
}
int main()
{
	int arr[3][5] = { {1, 2, 3, 4, 5},{2, 3, 4, 5,6 },{3, 4, 5, 6, 7} };
	print(arr, 3, 5);
	return 0;
}

print函数传递arr表示数组中首元素(是数组)的地址,也就是{1,2,3,4,5}的地址,也是1的地址,通过数组指针的形式接收参数,p+1后就跳过真个数组,地址从第一个数组到第二个数组,通过这种操作可以达到换行的目的。
打印二维数组

传参

一维数组传参:

void test(int arr[])
{}
void test(int arr[10])
{}
void test(int *arr)
{}
void test2(int* arr2[])
{}
void test2(int* *arr2)
{}
int main()
{
	int arr[10] = { 0 };
	int* arr2[10] = { 0 };  //同样arr2指的也是首元素地址。
	test(arr);
	test2(arr2);
	return 0;
}

二维数组传参以及一些错误示范:

//自定义函数中行可以省,列必须有。
void test1(int arr[3][5])
{}
void test1(int arr[][5])
{}
//这里的5不能省,少了会报错,如下图。
void test1(int (*arr)[5])
{}
//错误示范
void test1(int (*arr)[]) 
{}
 void test1(int **arr)
 {}
 void test1(int *arr)  //首元素是数组地址,因此得用数组指针
 {}
int main()
{
	int arr[3][5] = { 0 };
	test1(arr);
	return 0;
}

数组指针传参报错

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值