C语言:指针2(超详细讲解)

 

目录

数组名的理解

使用指针访问数组

一维数组传参的本质

冒泡排序

指针数组

指针数组模拟二维数组


数组名的理解

在一维数组中我们需要通过数组首元素地址来访问全部元素

这⾥我们使⽤ &arr[0] 的⽅式拿到了数组第⼀个元素的地址,但是其实数组名本来就是地址,⽽且
是数组⾸元素的地址,我们来做个测试

下面这个代码我们可以看到地址是一样的说明&arr[0]和arr拿到的都是数组首元素的地址

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("&arr[0] = %p\n", &arr[0]);//&arr [0]
	printf("arr     = %p\n", arr);    //arr
}

其实数组名其实是首元素地址但是有2个例外

sizeof ( arr ) :这⾥的数组名表⽰的是整个数组,比如下面这个代码有10个元素每个元素是int类型,int类型是4个字节,10个元素就是40个字节

& arr  : 这⾥的数组名也是表⽰整个数组,

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("%d", sizeof(arr));
}


看看下面这个代码我们可以看到&arr和&arr[0]拿到的是数组首元素地址,

但是&arr+1的话是加40个字节,也就是整个数组

&arr[0]+1是加4个字节

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("&arr    = %p\n", &arr);
	printf("&arr[0] = %p\n", &arr[0]);
}


使用指针访问数组

下面代码我们可以看到数组有10个元素都是0

int* p指向数组首元素地址

循环输入:p一直都是首元素地址不会变,+ i跳过i个字节

打印的话p的首元素地址也不会变+i跳过i个字节然后解引⽤

int main()
{
	int arr[10] = { 0 };
	//计算数组有多少个元素
	int sz = sizeof(arr) / sizeof(arr[0]);
	//指向数组首元素地址
	int* p = &arr[0];
	//输入
	for (int i = 0;i < sz; i++)
	{
		scanf("%d", p + i);
	}
	//打印
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", *(p+i));
		/*p++;*/
	}
}


一维数组传参的本质

我们这个sz计算数组有多少个元素

但是为什么一维数组传参给函数会变成1呢

因为传给函数的是数组首元素地址这个地址是int类型int是4个字节

4 / 4 = 1

void add(int arr[])
{
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("%d\n", sz);
}
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("%d\n", sz);
	add(arr);
}


⼀维数组传参,形参的部分可以写成数组的形式,也可以写成指针的形式


冒泡排序

冒泡排序我们可以把一组很乱的数值排好

很乱的数值:9 7 6 4 3 1 2 6 8 10

排好:1 2 3 4 5 6 7 8 9 10

冒泡排序的核⼼思想就是:两两相邻的元素进⾏⽐较

void sr(int arr[], int sz)
{
	for (int i = 0; i < sz; i++)
	{
		scanf("%d", &arr[i]);
	}
}
//冒泡排序
void jh(int arr[], int sz)
{
	for (int i = 0; i < sz - 1; i++)
	{
		for (int j = 0; j < sz - 1 - i; j++)
		{
			//判断
			if (arr[j] > arr[j + 1])
			{
				//交换
				int r = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = r;
			}
		}
	}
}
//打印
void day(int arr[], int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}
int main()
{
	int arr[10] = { 0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	//输入10个数值
	sr(arr, sz);
	//进行冒泡排序
	jh(arr, sz);
	//打印
	day(arr, sz);
}

这代码我们可以看到输入10个数值然后进行排序然后打印


输入10个数值


下面我们可以看到这个为什么是sz-1呢

因为我们排序到第9个数值就已经排序好了

最后的一个数值没必要排序

1  2  3  4  5  6  7  8  9  10


这第二个for循环

sz-1和上面一样

- i 是当我们排序完这个数值就不用排序了


这个是j是第1数值,j+1是第二个数值

这2个数值进行比较第一个数组大于第二个数值的话这2个数值进行交换


最后就是打印了


指针数组

指针就是存放指针的数组

当我们需要创建很多个指针,总不能一个一个创建吧

我们就需要创建个指针数组把这些指针放进去就行了


下面这个就是把a,b,c的指针放到指针数组里

然后循环通过i访问下标把这3个值改成99,然后打印


 

当然指针数组里每个地址都是int*类型的,也可以说是指针

指针数组模拟二维数组

我们通过 i 来访问arr1,arr2,arr3

j是访问这些数组的每个元素

int main()
{
	int arr1[5] = {1,2,3,4,5};
	int arr2[5] = {2,3,4,5,6};
	int arr3[5] = {3,4,5,6,7};
	int* p[3] = { arr1,arr2,arr3 };
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			printf("%d ",p[i][j]);
		}
		printf("\n");
	}

 }

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值