快上网专注成都网站设计 成都网站制作 成都网站建设
成都网站建设公司服务热线:028-86922220

网站建设知识

十年网站开发经验 + 多家企业客户 + 靠谱的建站团队

量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决

C语言学习备忘录-指针进阶-各类型指针对比-创新互联

各类型指针对比

(特别鸣谢@比特鹏哥)

翔安网站建设公司成都创新互联公司,翔安网站设计制作,有大型网站制作公司丰富经验。已为翔安成百上千提供企业网站建设服务。企业网站搭建\外贸网站制作要多少钱,请找那个售后服务好的翔安做网站的公司定做!目 录 字符(串)指针 数组指针 数组传参和指针传参 函数指针 函数指针数组 总结大合集

############################################################################################################

字符(串)指针 指向字符(串)的指针
int main()
{char ch = 'q';
	char* pc = &ch;
	printf("%c %p %c\n", ch, pc, *pc);
	char* ps = "hello world";// 本质上是把字符串"hello world"的首元素地址放到*ps指针中
	char arr[] = "hello world";
	printf("%c\n", *ps);
	printf("%s\n", ps);
	printf("%c\n", arr[0]);
	printf("%s\n", arr);
	
	// 面试题
	char str1[] = "hello world";
	char str2[] = "hello world";
	char* str3 = "hello world";
	char* str4 = "hello world";// 常量池中的字符的地址相同 (这个地方还有待商榷,学艺不精待深入学习后再作解释)
	if (str1 == str2)// 数组名为数组首元素地址
	{printf("str1 is same to str2\n");
	}
	else
	{printf("str1 is not same to str2\n");
	}
	if (str3 == str4)
	{printf("str3 is same to str4\n");
	}
	else
	{printf("str3 is not to str4\n");
	}
	return 0;
}

运行结果:

数组指针 数组指针本质上是一种指针
int main()
{int arr[10] = {1,2,3,4,5 };// arr是数组首元素的地址 - arr[0]的地址
	int(*parr)[10] = &arr;// &数组名->取出的是整个数组的地址 parr就是一个数组指针 - parr中存放的就是这个数组的地址
	return 0;
}
(有关的题外话)

数组名就是数组首元素地址
But两个例外:
1、sizeof(数组名) ->数组名表示整个数组,计算的是整个数组的大小,单位是字节byte
2、&数组名 ->数组名表示整个数组,取出的是整个数组的地址

int main()
{int arr[10] = {0 };
	int* p1 = arr;
	int(*p2)[10] = &arr;
	printf("%p %p\n", arr, &arr);// 数组的首元素地址 = 数组的地址
	printf("%p %p\n", p1, p2);
	printf("%p %p\n", p1 + 1, p2 + 1);// 跨4字节(跨了一个数组元素) 跨40字节(跨了一整个数组)
	return 0;
}

运行结果:

数组指针的使用 一维数组
int main()
{// 一般不用于一维数组
	int arr[10] = {1,2,3,4,5,6,7,8,9,10 };
	int(*pa)[10] = &arr;
	int i = 0;
	for (i = 0; i< 10; i++)
	{printf("%d ", *((*pa) + i));
		// pa存放的是数组的地址,解引用(*pa)即得到arr数组名即*pa=arr,arr为数组首元素地址,解引用(*((*pa) + i))即一一取出数组中的元素
	}
	return 0;
}

运行结果:

二维数组
// p是一个指向一维数组的指针 - *p = arr[i](i = 0,1,2)
void print(int (*p)[5], int r, int c)
{int i = 0;
	int j = 0;
	for (i = 0; i< r; i++)
	{for (j = 0; j< c; j++)
		{	printf("%d ", *(*(p + i) + j));
			// p ->第1行的一维数组的地址(整个数组)
			// *p ->第1行的一维数组名
			// p + i<=>第(1+i)行的一维数组的地址
			// *(p + i)<=>arr[i][5] - 第(1+i)行一维数组的数组名
			// *(p + i) + j<=>第(1+i)行的一维数组名+j = 第(1+i)行的一维数组的首元素地址+j = 第(1+i)行(1+j)列元素的地址
			// *(*(p + i) + j)<=>第(1+i)行(1+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;
}

运行结果:

数组传参和指针传参 一级指针传参
void print(int* ptr, int sz)
{int i = 0;
	for (i = 0; i< sz; i++)
	{printf("%d ", *(ptr + i));
	}
}
void test(char* p)
{;
}
int main()
{int arr[10] = {1,2,3,4,5,6,7,8,9,10 };
	int* p = arr;
	int sz = sizeof(arr) / sizeof(arr[0]);
	// p是一级指针 - 一级指针传参一级指针接收
	print(p, sz);
	char ch = 'w';
	char* p1 = &ch;
	test(&ch);
	test(p1);
	return 0;
}

运行结果:

二级指针传参
void test(int** p2)
{// *p2 ->pa ->*pa ->a
	**p2 = 20;
}
int main()
{int a = 10;
	int* pa = &a;// pa是一级指针
	int** ppa = &pa;// ppa是二级指针
	// 把二级指针进行传参
	test(ppa);
	test(&pa);// 传一级指针变量的地址
	int* arr[10] = {0 };
	test(arr);// 传一级指针数组/传存放一级指针的数组
	printf("%d\n", a);
	return 0;
}
函数指针
int Add(int x, int y)
{return x + y;
}
int main()
{// 函数指针 - 存放函数地址的指针
	// &函数名 - 取到的就是函数的地址
	printf("%p\n", &Add);
	printf("%p\n", Add);
	// 数组名 != &数组名<->函数名 == &函数名 ==*函数名
	// pf就是一个函数指针变量
	int (*pf)(int,int) = &Add;
	return 0;
}

运行结果:

调用函数指针
int Add(int x, int y)
{return x + y;
}
int main()
{int (*pf)(int,int) = Add;
	int ret = (*pf)(3, 5);
	int ret = pf(3, 5);
	int ret = Add(3, 5);
	// Add == *pf == pf ==****....***pf - 我不理解但我大受震撼
	// 函数名本身也是一个地址
	printf("%d\n", ret);
	// void(*)() - 函数指针类型
	// (void(*)())0 - 对0进行强制类型转换,被解释为一个函数地址
	// *((void(*)())0) - 对0地址进行了解引用操作
	// (*((void(*)())0)(); - 调用0地址处的函数

	// void (*)(int) - 函数指针类型
	// signal(int, void (*)(int)) - signal()函数,函数参数1是int类型,函数参数2是函数指针类型(返回类型void,参数是int)
	// void (* signal(int, void (*)(int)))(int) - void (*signal())(int) - signal函数指针类型,返回值是void,参数是int
	return 0;
}
函数指针数组

存放函数指针的数组

int Add(int x, int y)
{return x + y;
}
int Sub(int x, int y)
{return x - y;
}
int main()
{int (*pf1)(int, int) = Add;
	int (*pf2)(int, int) = Sub;
	int (*pfArr[2])(int, int) = {Add,Sub };// pfArr是一个函数指针数组 - 存放同类型的函数指针
	return 0;
}
总结大合集
// 常规int*指针
int* p = &a;
// 字符串指针
char* pc = &ch;
// 数组指针
int(*pa)[10] = &arr;
// 函数指针
int (*pf)(int,int) = &Add;
// 函数指针数组
int (*pfArr[2])(int, int) = {Add,Sub };

(其实就是对比一下几种指针长啥样子,因为学的太多太深然后逐渐分不清,脑袋一片浆糊,分类学完后再总结对比一下,会有新发现)

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


网站名称:C语言学习备忘录-指针进阶-各类型指针对比-创新互联
地址分享:http://6mz.cn/article/dssphi.html

其他资讯