学习指针这篇文章就够了!【c语言】-创新互联

文章目录
  • 1.指针是什么?
  • 2.指针和指针类型
    • 2.1指针的解引用
  • 3.野指针
    • 3.1野指针成因
      • 指针未初始化
      • 指针越界访问
      • 指针指向的空间释放
    • 3.2如何规避野指针
  • 4.指针运算
    • 4.1指针+- 整数
    • 4.2指针-指针
    • 4.3指针的关系运算
  • 5.指针和数组
  • 6.二级指针
  • 7.指针数组

创新互联公司是一家集网站建设,定日企业网站建设,定日品牌网站建设,网站定制,定日网站建设报价,网络营销,网络优化,定日网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。1.指针是什么?

指针是内存中一个最小单元的编号 ,也就是地址
平时口语中说的指针其实本质上是指针变量,是用来存放内存地址的变量

  • 内存
    在这里插入图片描述

一个字节为一个内存单元,我们可以通过编号找到内存 ,编号在生活中叫地址,对应我们c语言其实就是指针

#includeint main()
{int a = 10;
int *p = &a;
return 0;
}

那我们&a是取出的是哪一个字节的地址?取出的是第一个字节的地址(较小的地址)
在这里插入图片描述

  • 内存单元是如何进行编号?

在32位机器上,地址就是32个0或1组成二进制序列,那地址就得用用4个字节的空间进行储存 ,也就是说32位机器,指针变量大小就是4个字节
在64位机器上,地址就是64个0或1组成二进制序列,那地址就得用用8个字节的空间进行储存 ,也就是说64位机器,指针变量大小就是8个字节

2.指针和指针类型
int main()
{int a = 0x11223344;
	char* pc = (char*)&a;
	int i = 0;
	for (i = 0; i< 4; i++)
	{*pc = 1;
		pc++;
	}
	return 0;
}
  • 指针类型的不同意义:指针的不同类型提供了不同的视角去观看和访问内存

指针的不同类型决定了,指针在解引用的时候一次性访问几个字节,决定了访问权限的大小
如果是char *的指针,解引用访问一个字节
如果是int *的指针,解引用访问四个字节

int main()
{int a = 0x11223344;
	int* pa = &a;
	char* pc = &a;

	printf("%p\n", pa);
	printf("%p\n", pa+1);

	printf("%p\n", pc);
	printf("%p\n", pc+1);

	return 0;
}

在这里插入图片描述

指针类型决定了指针+1跳过几个字节(步长)
如果是字符指针 ,+1跳过一个字节
如果是整形指针 ,+1跳过四个字节

2.1指针的解引用
#includeint main()
{int n = 0x11223344;
	char* pc = (char*)&n;
	int* pi = &n;
	*pc = 0; 
	*pi = 0; 
	return 0;
}
3.野指针

野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)

3.1野指针成因 指针未初始化
#includeint main()
{int *p;
  *p = 20;
return 0;
}

局部变量指针未初始化,默认为随机值

指针越界访问
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\n", *p );
		p++;
	}
	return  0;
 }

当指针指向的范围超过数组arr的范围 , p 就是野指针

指针指向的空间释放
int* test()
{int a = 10;
	return &a;
}
int main()
{int *p = test();
	printf("hehe\n");

	printf("%d\n", *p);

	return 0;
}
3.2如何规避野指针
  • 指针初始化
int main()
{int  a = 10;
	int* pa = &a;
	return 0;
}

如果实在不知道指针指向哪里 也需要初始化

#includeint main()
{int* p = NULL;
	if (p != NULL)
	{}
	return 0;
}
  • 使用assert(断言)

assert中可以放一个表达式,如果表达式为假就报错,如果为真就什么也不发生
举个例子

void  * my_strcpy(char* dest, const char* src)
{ assert(dest && src);//断言指针的有效性
	 //assert(dest!= NULL)
	 //assert(src!= NULL)
	 while (*dest++ = *src++)
	 { ;
	 }
 }
int main()
{char arr1[] = "hello";
	char arr2[20] = {0 };
	my_strcpy(arr2, arr1);
	printf("%s\n", arr2);
	return 0;
}
  • 小心指针越界
  • 指针指向空间释放,及时设置NULL
  • 避免返回局部变量的地址
  • 指针使用之前检查有效性
4.指针运算 4.1指针± 整数 4.2指针-指针

前提 :两个指针要指向同一块空间
指针-指针的绝对值得到的是两个指针之间的个数

int main()
{char ch[5] = {0};
	int arr[10] = {0 };
	printf("%d\n", &arr[0] - &arr[9]);
	return 0;
}

在这里插入图片描述

4.3指针的关系运算

标准规定:允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。
也就是说可以允许向后找到越界的地址和数组某个元素进行比较,但是不允许向前越界找到的地址和数组某个元素进行比较。这里的越界是指跳出了自己的范围,并没有非法访问越界之后的指针。这里只是比较大小。

#define N_VALUES 5
float values[N_VALUES];
float *vp;
for(vp = &values[N_VALUES]; vp >&values[0];)
{*--vp = 0;
}

在这里插入图片描述

5.指针和数组

指针和数组是不同的对象
指针是一种变量,用来存放地址,大小为4/8个字节。
数组是一组相同类型元素的集合,是可以存放多个元素的,大小取决于元素个数和元素类型。
数组的数组名是数组首元素的地址,地址是可以放在指针变量中,可以通过指针访问数组。

6.二级指针
int main()
{int a = 10;
	int* pa = &a;
	int* * ppa = &pa;
	return 0;
}

在这里插入图片描述

在这里插入图片描述

pa是一级指针变量 ,ppa 是二级指针变量。 a 开辟了一块内存,用来存放数据 ,数据为10。 a的地址是0x0012ff40。 pa里面存放a的地址

7.指针数组

存放指针的数组
使用一维数组模拟二维数组

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

在这里插入图片描述

关于arr [i] [ j] 的解释: arr[ i] 当i 为 0 , 1 ,2 时 arr [0] 访问的是a数组首元素地址 arr[1] 访问的是b数组首元素的地址 arr[ 2] 访问的是c数组首元素的地址
在这里插入图片描述
*(arr [0] + j ) 当j是 0 , 1,2,3 时 ,就可以等价于 arr[0] [j ]


如果你觉得这篇文章对你有帮助,不妨动动手指给点赞收藏加转发,给鄃鳕一个大大的关注
你们的每一次支持都将转化为我前进的动力!!!
在这里插入图片描述

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


网页名称:学习指针这篇文章就够了!【c语言】-创新互联
文章源于:http://azwzsj.com/article/dcgcis.html