C语言——指针(2)

1.字符指针

这是一个简单的字符指针的用法

int main() {
	char a = 'b';
	char* p = &a;
	*p = 'c';
    return 0;
}

那如果一个字符串赋给指针数组会怎么样呢?

int main() {
	char* p = "abcdef";
    return 0;
}

在32位机器下,指针大小为4个字节,那这个指针肯定无法将这个字符串的所有元素地址保存下来

调试起来我们发现p指针实际上存了常量字符串的首元素‘a’的地址

 当然,我们也可以打印出来直观的看一下

#include<stdio.h>
int main() {
	char* p = "abcdef";
	printf("%c\n", *p);
}

 

如果你要打印整个字符串,可以这样

#include<stdio.h>
int main() {
	char* p = "abcdef";
	printf("%s\n", p);
}

注意:这里的常量字符串“abcdef”

这个字符串是不允许修改的,如果要强行修改,会使程序崩溃

int main() {
	char* p = "abcdef";
	*p = 'w';//这里是一个错误的写法
}

我们通常都会在前面加一个const,保证内容无法修改 

int main() {
	const char* p = "abcdef";
}

2.指针数组

本质上就是把数组中原来储存整形,字符,浮点型的元素换成储存地址的元素

int main() {
	int a = 10;
	int b = 9;
	int c = 5;

	int* arr[3] = {&a,&b,,&c};//存放指针类型的数组——指针数组
}

int main() {
	int arr1[3] = { 1,2,3 };
	int arr2[3] = { 2,3,4 };
	int arr3[3] = { 3,4,5 };

	int* p[3] = {arr1,arr2,arr3};
	return 0;
}

 再来看一个例子

int main() {
	int arr1[3] = { 1,2,3 };
	int arr2[3] = { 2,3,4 };
	int arr3[3] = { 3,4,5 };

	int* p[3] = {arr1,arr2,arr3};


	return 0;
}

这样就模拟了一个二维数组 

#include<stdio.h>
int main() {
	int arr1[3] = { 1,2,3 };
	int arr2[3] = { 2,3,4 };
	int arr3[3] = { 3,4,5 };

	int* p[3] = {arr1,arr2,arr3};

	int i = 0;
	for (i = 0;i < 3;i++) {
		int j = 0;
		for (j = 0;j < 3;j++) {
			printf("%d ", p[i][j]);//类似于二维数组的引用方式
		}
		printf("\n");
	}
	return 0;
}

3.数组指针

数组指针的定义

数组指针是指针

对于整形指针,int* p,是能够指向整形数据的指针

数组指针是:能够指向数组的指针

对比一下指针数组和数组指针:

	int* p1[10];//指针数组
	int(*p2)[10];//数组指针,[10]中的10不可省略

[  ]的优先级高于 *,对于第一个来说 p1先与[  ]结合

而第2个加上了括号,*先与p2结合

注意:数组指针int (*p)[10]中的[10]表明该指针指向的数组是有十个元素的数组,而不是该指针存了数组中十个元素的地址

 我们看这样的代码

#include<stdio.h>
int main() {
	int arr[10] = { 0 };

	printf("%p\n", arr); //类型:int*
	printf("%p\n", arr + 1);

	printf("%p\n", &arr[0]); //类型:int*
	printf("%p\n", &arr[0] + 1);

//&arr是取出整个数组的地址
	printf("%p\n", &arr);//类型:int(*)[10]
	printf("%p\n", &arr + 1);//+1直接跳过整个数组的大小

}

 那对于这样的&arr,我们应该如何储存?

    int* p1 = &arr;//错误,原因是类型不同,int(*p)[10]无法转化到int*
    int(*p)[10] = &arr;//正确

我们就用数组指针

 

 这里&arr的类型是int (*)[10]

我们通过这个例子,运用一下数组指针

void print1(int* arr, int sz) {
	int i = 0;
	for (i = 0;i < sz;i++) {
		printf("%d ", *(arr + i));
	}
}
int main() {//依次打印数组中的元素
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
		int sz = sizeof(arr) / sizeof(arr[0]);
		print1(arr, sz);
		return 0;
}

运用数组指针 

void print1(int(*p)[10], int sz) {
	int i = 0;
	for (i = 0;i < sz;i++) {
		//*p=*(&arr)=arr,*与&相抵消,所以*p相当于数组名,数组名是首元素地址,所以*p就是&arr[0]
		printf("%d ", *(*p + i));
	}
}
int main() {
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	print1(&arr, sz);
	return 0;
}

 这种写法复杂,不推荐,仅用于例子

我们再来看一个二维数组的例子

#include<stdio.h>
void print1(int arr[3][5], int c, int r) {//打印二维数组
	int i = 0;
	for (i = 0;i < 3;i++) {
		int j = 0;
		for (j = 0;j < 5;j++) {
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}
int main() {
	int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
	print1(arr, 3, 5);
}

用数组指针可以这样 

void print1(int (*p)[5], int c, int r) {
	int i = 0;
	for (i = 0;i < c;i++) {
		int j = 0;
		for (j = 0;j < r;j++) {
			//*(p+i)拿到第i行的数组名,也就是拿到第i行第一个元素的地址
			printf("%d ", *(*(p + i)+j));//也可写成p[i][j]
		}
		printf("\n");
	}
}
int main() {
	int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
	print1(arr, 3, 5);
}

*(*(p+i)+j)是p[ i ] [ j ]更本质的表现

当传参是数组指针时

arr[ i ] = *(*arr+i)

arr[ i ][ j ] = *(arr+i)[ j ] = *(*(arr+i)+j)

通常解两次引用可获取到元素,第一次解引用,是抵消&,得到数组名,第二次是得到数组名(地址)中的元素

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橘子13

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值