资讯专栏INFORMATION COLUMN

【C语言】指针详解

wangtdgoodluck / 905人阅读

摘要:指针的大小是固定的个字节位平台位平台。二指针数组指针数组是一个存放指针的数组。是一个数组指针,该指针指向的数组有个元素,每个元素都是的。错误错误二维数组首元素指的是第一行。

前言

指针概念

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

一、字符指针

int main(){	char ch = "w";	char *pc = *ch;//pc是指向一个常量字符串		const char *p = "helloworld";	//"helloworld"是一个常量字符串,存在在内存的常量区。不能更改	//上面表达式的意思是把常量表达式"helloworld"的第一个字符h的地址赋值给p	printf("%c/n", *p);//h	printf("%s/n", p);//helloworld	return 0;}

例题一

int main(){	char str1[] = "hello bit.";	char str2[] = "hello bit.";	const char *str3 = "hello bit.";//常量字符串,不能修改	const char *str4 = "hello bit.";	if (str1 == str2)		printf("str1 and str2 are same/n"); //用相同的常量字符串去初始		//化不同的数组的时候就会开辟出不同的内存块。所以str1和str2不同	else		printf("str1 and str2 are not same/n");	if (str3 == str4)		printf("str3 and str4 are same/n");//当几个指针指向同一个字符串的时候,他们实际会指向同一块内存	else		printf("str3 and str4 are not same/n");	return 0;}

运行结果:

这里str3str4指向的是同一个常量字符串。C/C++会把常量字符串存储到多带带的一个内存区域,当几个指针指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。所以str1str2不同,str3str4不同。

二、指针数组

指针数组是一个存放指针的数组

	char *arr[5];// arr是存放字符指针的数组	int  *arr[5];// arr是存放整形指针的数组

例题一

int main(){	int a = 0;	int b = 20;	int c = 30;	int d = 40;	int *arr[4] = {&a, &b, &c, &d};	//arr就是整形指针的数组。数组共4个元素,每个元素都是int*类型	for (int  i = 0; i < 4; i++)	{		printf("%d ", *(arr[i]));  //0 20 30 40	}	return 0;}

例题二

int main(){	int arr1[] = { 1, 2, 3, 4, 5 };	int arr2[] = {6, 7, 8, 9, 10};	int arr3[] = { 2, 3, 4, 5, 6 };	int *parr[] = { arr1, arr2, arr3 };//存储每个数组的首地址	for (int i = 0; i < 3; i++)	{		for (int  j = 0; j < 5; j++)		{			printf("%d ", parr[i][j]);//p[i] = *(p +i)			//parr[i][j] = *(parr[i] +j)		}		printf("/n");	}	return 0;}

输出结果:

例题三

int main(){	const char *arr[5] = {"abcdef","bcdef","hehe","zhangsan","haha"};	//字符指针的数组,指针里面存储每个字符串的首地址。	int i = 0;	for ( i = 0; i < 5; i++)	{		printf("%s/n", arr[i]);	}	return 0;}

三、数组指针

3.1数组指针的定义

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

int *p1[10];//指针数组int (*p2)[10];//数组指针

例题一

int main(){	int arr[10] = { 0 };	int *p = arr;//arr是数组首元素的地址	int (*parr)[10] = &arr;//取出的是数组的地址,应该存放在数组指针中	//parr类型为int(*)[10]	return 0;}

int (*p)[10]的解释:
解释p先和*结合,说明p是一个指针变量,然后指向的是一个大小为10个整型的数组。所以p是一个指针,指向一个数组,叫数组指针
【注意】:[]的优先级要高于*号的,所以必须加上()来保证p先和*结合。

例题二

#include int main(){	int arr[10] = { 0 };	printf("%p/n", arr);//数组名是首元素的地址(arr arr[0]),类型为int*	printf("%p/n", &arr[0]);//类型为int*	printf("%p/n", &arr);//取出数组的地址(&arr)     类型为int*(10)	//上面三行输出的结果一样,都为012FF804	printf("%p/n", arr +1);  //012FF808	printf("%p/n", &arr[0] + 1); //012FF808	printf("%p/n", &arr + 1);  //012FF82C  数组指针+1,跳过一个数组	return 0;}

3.2 &数组名VS数组名

数组名是首元素地址,但是有两个例外:
1.sizeof(arr)/sizeof(数组名)这里的数组名是表示整个数组sizeof(数组名)计算的是整个数组的大小,单位是字节
2.&(数组名),这里的数组名不是首元素的地址,数组名表示整个数组,所以取出的是整个数组的地址
数组的地址+1,跳过整个数组的大小。

3.3数组指针的使用

例题一

void print1(int arr[], int sz){	int i = 0;	for (i = 0; i < sz; i++)	{		printf("%d ", arr[i]);	}}void print2(int* arr, int sz){	int i = 0;	for (i = 0; i < sz; i++)	{		printf("%d ", *(arr + i));	}}void print3(int (*parr)[10], int sz)//这是一个错误的示范,这是parr指向的是整个数组,+1跳过的是整个数组{	int i = 0;	for (i = 0; i < sz; i++)	{		printf("%d ", parr[i]);//parr[i] == *(parr+i)	}}void print4(int (*parr)[10], int sz){	//*(parr + 0);-->parr[0]	int i = 0;	for (i = 0; i < sz; i++)	{		//printf("%d ", parr[0][i]);		//printf("%d ", (*(parr + 0))[i]);		printf("%d ", (*parr)[i]);//(*parr) 相当于 parr指向的数组的数组名	}}int main(){	int arr[10] = {1,2,3,4,5,6,7,8,9,10};	int sz = sizeof(arr) / sizeof(arr[0]);	print4(&arr, sz);	//print3(&arr, sz);	//print2(arr, sz);	//print1(arr, sz);//打印arr数组的内容	return 0;}

例题二

void printf1(int arr[3][5], int r, int c){	for (int i = 0; i < r; i++)	{		for (int j = 0; j < c; j++)		{			printf("%d ", arr[i][j]);		}		printf("/n");	}}void printf2(int (*p)[5], int r, int c){	for (int i = 0; i < r; i++)			{				for (int j = 0; j < c; j++)				{					//printf("%d ", *(*(p+i)+j));					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 };	//二维数组传参	//printf1(arr, 3, 5);	printf2(arr, 3, 5);  //arr是数组名,数组名是首元素(二维数组的第一行)地址(是二维数组每一行的一维数组首元素的地址)可以数组指针来接收	return 0;}

例题三

int arr[5];:整形数组
int *parr1[10];parr1是一个数组,10个元素,每个元素是int*的,所以parr1是一个存放指针的数组
int (*parr2)[10];parr2是一个数组指针,该指针指向的数组有10个元素,每个元素都是int的。
int (*parr3[10])[5];parr3是一个数组,数组有10个元素,每个元素是一个数组指针,该指针指向的数组有5个元素,每个元素是int的。

四、 数组参数、指针参数

4.1 一维数组传参

#include void test(int arr[])//ok{}void test(int arr[10])//ok{}void test(int *arr)//ok{}void test2(int* arr[20])//ok,20可以省略{}void test2(int** arr)//ok,一级指针的地址传过去,要用一个二级指针接收{}int main(){	int arr[10] = {0};	int *arr2[20] = {0};	test(arr);	test2(arr2);}

4.2 二维数组传参

void test(int arr[3][5])//ok{}void test(int arr[][])//错误{}void test(int arr[][5])//ok{}//总结:二维数组传参,函数形参的设计只能省略第一个[]的数字。//因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。//这样才方便运算。void test(int *arr)//错误{}void test(int* arr[5])//错误{}void test(int (*arr)[5])//ok 二维数组首元素指的是第一行。{}void test(int **arr)//错误{}int main(){	int arr[3][5] = {0};	test(arr);}

4.3 一级指针传参

#include void print(int *p, int sz){	int i = 0;	for(i=0; i<sz; i++)	{	printf("%d/n", *(p+i));	}}int main(){	int arr[10] = {1,2,3,4,5,6,7,8,9};	int *p = arr;	int sz = sizeof(arr)/sizeof(arr[0]);	//一级指针p,传给函数	print(p, sz);	return 0;}

当一个函数的参数部分为一级指针的时候,函数能接收什么参数?

void test1(int *p){}int main(){	int a = 10;	int *p1 = &a;	int arr[10] = { 0 };	test(&a);	test(arr);	test(p1);	return 0;}

4.4 二级指针传参

当函数的参数为二级指针的时候,可以接收什么参数?

#include void test(int** ptr){	printf("num = %d/n", **ptr);}int main(){	int n = 10;	int*p = &n;	int **pp = &p;	int *arr[5];	test(pp);	test(&p);	test(arr);	return 0;}

五、函数指针

函数指针变量:存放函数的地址
函数名&函数名是一样的。

int Add(int x, int y){	return x + y;}int main(){	//printf("%p/n", Add);	int(*pf)(int, int) = &Add;//pf是用来存放函数的地址,-pf就是函数指针变量	//函数指针类型:int(*)(int, int) 	int ret = Add(4, 5);	printf("%d/n", ret);	ret = (*pf)(4, 5); //*可以没有,也可以写多个	ret = pf(4, 5);	printf("%d/n", ret);//9	return 0;} 

例题一

(*(
            
                     
             
               

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/120813.html

相关文章

  • C语言指针这一篇够了(一万二千字,包含指针与数组,函数指针详解

    摘要:指针变量可以存放基本类型数据的地址,也可以存放数组函数以及其他指针变量的地址。数组名表示的是整个数组所占的字节数。在这里数组指针的类型是。这也是我们可以用数组指针来接收二维数组数组名的原因。 目录 零.前言 一.指针的定义 二.指针类型的意义 1.指针类型决定了指针解引用时一次访问几个字...

    My_Oh_My 评论0 收藏0
  • C语言qsort()函数的使用(详解

    摘要:参数含义上图是函数各个参数的含义,让我们一个个来看。使用方式头文件要使用函数我们首先需要引用一个头文件的实现函数给函数规定了特定的参数。因此我们设计函数时要严格遵守其参数设定。 目录 1.参数含义 1.首元素地址base 2.元素个数num 3.元素大小size 4.自定义比较函数compa...

    wangym 评论0 收藏0
  • C语言 指针+二维数组详解 (应付期末、考研的最强笔记,建议收藏)

    摘要:需要注意的是用矩阵形式如行列表示二维数组,是逻辑上的概念,能形象地表示出行列关系。再次强调二维数组名如是指向行的。一维数组名如是指向列元素的。 哈喽!这里是一只派大鑫,不是派大星。本着基础不牢,地动山摇的学习态度,从基础的C语言语法讲到算法再到更高级的语法及框架的学习。更好地让同样热爱编...

    FrozenMap 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<