详解C指针 (一)

1.前言-指针的概念

(1). 指针是变量,用来存放地址,地址唯一标识一块内存空间。
(2). 指针大小是固定的 4/8 个字节(32位平台/64位平台)。
(3). 指针是有类型的,决定了指针的 +- 整数的步长,指针解引用操作时的权限。
(4). 指针的运算。

2. 字符指针

//char*

char ch = 'w';
//ch = 'a';
char* pc = 'w';//pc为字符指针
*pc = 'a';
再看这种形式:
char arr[] = "abcdef"; //字符数组中存放[a b c d e f \0]

const char* pc = "abcdef"; //"abcdef"是常量字符串,首字母a的地址放在pc中,pc的类型是char*

3. 指针数组

指针数组是一个存放指针的数组
//整形数组 - 存放整形的数组
//字符数组 - 存放字符的数组
//指针数组 - 存放指针的数组

int arr1[10]; //存放整形的数组
int* arr2[10]; //存放整形指针的数组 - 整形指针数组
char* arr3[10]; //字符指针数组
char** arr4[10]; //二级字符指针数组
使用指针数组模拟实现二维数组
#include 

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

	int* arr[3] = { arr1, arr2, arr3 };//指针数组
	
    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");
	}
	
	return 0;
}

详解C指针 (一)_第1张图片

4.  数组指针

数组指针本质是指针
int* num1; //指向整形变量的指针,存放整形变量地址的指针变量

float* num2; //指向浮点型变量的指针

char* ch1; //指向字符型变量的指针

int *p1[10]; //指针数组
int (*p2)[10]; //数组指针,指向数组的指针,存放的是数组地址的指针变量 
               //p2是数组指针变量,指向int [10]数组
&数组名与数组名
//数组名是数组首元素的地址
//数组名表示首元素地址有两个例外
//1. sizeof(数组名),这里的数组不是首元素的地址,数组名表示整个数组。
//sizeof(数组名)计算的是整个数组的大小。单位是字节。
//2. &数组名,这里的数组名仍然表示整个数组,取出的是整个数组的地址
//除此之外,所有的地方数组名都是数组首元素的地址

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);

	printf("%p\n",&arr);//int(*)[10]
	printf("%p\n", &arr + 1);//跳过整个数组

	//printf("%d\n", sizeof(arr));
	
	return 0;
}
通过调试发现&arr[0],与&arr类型不同,但指向的都是首元素的地址

详解C指针 (一)_第2张图片

且arr+1与arr[0]+1都是跳过4个字节,而&arr+1跳过整个数组

详解C指针 (一)_第3张图片

因此数组指针的写法为:
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int(*p)[10] = &arr;//数组的地址,存放到数组指针变量,类型:int (*)[10]
//int[10] * p = &arr;//error
数组指针的使用:
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	/* int* p = arr;
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ",*(p+i));
	}*/
	int(*p)[10] = &arr;//数组的地址,存放到数组指针变量,类型:int (*)[10]
	int i = 0;
	for (i = 0; i < 10; ++i)
	{
		printf("%d ",(*p)[i]);//*&arr-->arr;
		//printf("%d ", *((*p) + i));
	}

	return 0;
}
上述代码利用数组指针后反而变得复杂了,那么数组指针如何正确使用呢?一般在二维数组使用中比较方便。代码如下:
void Print(int(*p)[5], int r, int c)//int(*p)[5]-二维数组第一行
{
	int i = 0;
	for (i = 0; i < r; i++)
	{
		int j = 0;
		for (j = 0; j < c; j++)
		{
			printf("%d ", *(*(p + i) + j)); //p->第一行
			//printf("%d ",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 };
	//二维数组首元素地址是第一行的地址
	//一维数组的地址-数组的地址
	Print(arr,3,5);
	return 0;
}

 5. 函数指针

首先看一段代码:
//数组指针 - 指向数组的指针
//函数指针 - 指向函数的指针

int Add(int x, int y)
{
	return x + y;
}

int main()
{
	printf("%p\n", Add);
	printf("%p\n", &Add);
	//函数名是函数的地址
	//&函数名也是函数的地址
	int(*pf)(int, int) = &Add;
	//int(*pf)(int, int) = Add;
	//int(*)(int,int)是函数指针类型

	int ret1 = Add(3,5);
	printf("%d\n", ret1);

	int ret2 = (*pf)(3, 5);
	printf("%d\n", ret2);

	int ret3 = pf(3, 5);
	printf("%d\n", ret3);

	return 0;
}
运行结果:

详解C指针 (一)_第4张图片


你可能感兴趣的:(C语言,c语言)