【c语言】深入理解指针(1)

 1. 数组名的理解

数组名是数组首元素的地址:

【c语言】深入理解指针(1)_第1张图片

但是有两个例外:

1. sizeof(数组名),sizeof中单独放一个数组名的时候,这里的数组名表示的是整个数组,计算的是整个数组的大小,单位是字节。

【c语言】深入理解指针(1)_第2张图片

2. &数组名,这里的数组名表示的是整个数组,取出的是整个数组的地址(整个数组的地址和数组首元素的地址是有区别的)。

【c语言】深入理解指针(1)_第3张图片

可以看到&arr + 1后地址是跳过40个字节的(这刚好是整个数组的大小),而其余两种的+1都只是跳过4个字节(这刚好是整型变量的大小)而已。

2. 使用指针访问数组

在使用指针访问数组的时候我们一般会这样写:

int main()
{
	int arr[10] = { 0 };
	int* p = arr;
	for (int i = 0; i < 10; i++)
	{
		scanf("%d", p + i);
	}
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", *(p+i));
	}
    return 0;
}

但是值得注意的是在打印指针内容的时候无论是写成*(p + i)还是写成p[i]亦或是写成i[p]编译器都会转换成*(p + 1)的形式去运算,所以最终所得的结果都是相同的,同理arr[i]也可以写成*(arr + i)和i[arr].

【c语言】深入理解指针(1)_第4张图片

3. 一维数组的传参的本质

1. 数组传参的时候,形参是可以写成数组的形式的,但是本质上还是指针变量,传过去的只是数组首元素的地址而已,所以实参的地址和形参访问的地址是同一个地址。

【c语言】深入理解指针(1)_第5张图片

2. 形参的数组是不会在单独创建数组空间的,所以形参的数组是可以省略数组的大小的,即直接写成arr[ ]的形式。

4. 指针数组

存放指针的数组就是指针数组。

指针数组的每个元素都是用来存放地址(指针)的。

指针数组的每个元素都是地址,又可以指向一块区域。

5. 指针模拟二维数组

二维数组:

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

利用指针模拟二维数组: 

我们可以将上面的arr数组分成三个一维数组,然后用指针数组模拟出二维数组。

int arr1[5] = { 1,2,3,4,5 };
	int arr2[5] = { 2,3,4,5,6 };
	int arr3[5] = { 3,4,5,6,7 };

1. 指针数组的存放。

创建一个指针数组分别存放三个一维数组的首地址。

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

2. 访问指针数组

可以利用解引用的方式访问指针数组,首先访问首地址的元素,然后根据分别访问首地址对应的一维数组。

for (int i = 0; i < 3; i++)
{
	for (int j = 0; j < 5; j++)
	{
		printf("%d", *(*(arr + i) + j));
	}
	printf("\n");
}

因为无论我们写成*(p+i)和写成p[i],编译器都会转成*(p+i)的形式进行运算,所得的结果都是相同的,所以我们也可以利用下标访问的形式去访问指针数组:

for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			printf("%d", arr[i][j]);
		}
		printf("\n");
	}

完整代码:

#include
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* arr[] = {arr1,arr2,arr3};
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			printf("%d", arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

二维数组与利用指针模拟二维数组最终打印的结果都是一样的: 

【c语言】深入理解指针(1)_第6张图片

练习题:调整数组使奇数全部都位于偶数前面。

题目:

输入一个整数数组,实现一个函数,

来调整该数组中数字的顺序使得数组中所有的奇数位于数组的前半部分,

所有偶数位于数组的后半部分。

基本思路:

取出数组最左边的地址和最右边的地址,然后分别赋值给指针*right和指针*left,然后判断*left%2是否等于1(也就是判断*left是否为偶数)如果是就left++后再判断一次,直到判断出*right为偶数或者left>=right为止,同理再判断*right%2是否等于1。当二者都判断完后将*right和*left的值进行交换。

完整代码:

#include
void Func(int* p,int len)
{
	int* left = p;
	int* right = p + len - 1;
	while (left < right)
	{
		while (left < right && *left % 2 != 0)
		{
			left++;
		}
		while (left < right && *right % 2 == 0)
		{
			right--;
		}
		int tmp = *left;
		*left = *right;
		*right = tmp;
	}
}
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9 };
	int len = sizeof(arr) / sizeof(arr[0]);
	Func(arr,len);
	for (int i = 0; i < len; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

执行结果: 

你可能感兴趣的:(c语言,c语言,学习,开发语言)