初识指针--基本概念

指针概念

在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”。意思是通过它能找到以它为地址的内存单元。

指针和指针类型

指针简单举例

#include<stdio.h>
int main(){
	int a=10;//在内存中开辟一块空间
	int * pa=&a; //pa就是存放地址的指针,而pa就是指针变量。
	
	return 0;
}

总结:指针就是变量,用来存放地址的变量。(存放在指针中的值都被当成地址处理)。

指针类型的意义

#include<stdio.h>
int main() {
	int a = 0x11223344;
	int *pa = &a;
	*pa = 0;

	return 0;
}

快捷键:Fn+F10或者F10,一步步看调试代码是地址中内容的变化:

这里a的地址的内容还是11223344(16进制)
继续按F10向下调试:当调试*pa=0;后可以发现地址的内容变化:
内容变化

而将int*pa=&a ;换成char *pc=&a ;时,会不会发生变化,下面我们就验证一下吧!

#include<stdio.h>
int main() {
	int a = 0x11223344;
	char *pc = &a;
	*pc = 0;

	return 0;
}

继续调试,看内存的变化:可以看出在第四行时a地址中的内容依然是十六进制的0x11223344;
char*
继续往下调试 * pc=0 ;后观察a地址中的内容变化:可以看出char *类型只改变一个字节的内容。

4

总结指针类型决定了指针解引用操作的时候,一次访问几个字节(访问内存的大小)。
例如:int * 解引用操作时访问4个字节;char * 解引用操作访问1个字节。

下面继续探索指针类型的意义:

#include<stdio.h>
int main() {
	int a = 0x11223344;
	int *pa = &a;
	char *pc = &a;

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

	return 0;
}

运行结果如图所示:

可以看出,指针类型+1步或者-1步时的步长。

由运行图可以看出:
int *类型到下一步步长为4个字节,char *到下一步的步长为1个字节。

野指针

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

野指针的原因

指针未初始化

#include <stdio.h>
int main()
{ 
 int *p;//局部变量指针未初始化,默认为随机值
 *p=20;
 return 0;
}

指针越界访问

#include <stdio.h>
int main()
{
    int arr[10] = {0};
    int *p = arr;
    int i = 0;
    for(i=0; i<=10; i++)
   {
        //当指针指向的范围超出数组arr的范围时,p就是野指针
        *(p++) = i;
   }
    return 0;
}

指针指向的空间释放

int * test(){
	int a=10;
	return &a;
}
#include<stdio.h>
int main(){
	int *p=test();
	printf("%d\n",*p);
	
	return 0;
}

如何规避野指针

各种例子说明:

#include <stdio.h>
int main()
{
    int *p = NULL;
    //指针指向NULL初始化
    int a = 10;
    p = &a;
    if(p != NULL)
   {
        *p = 20;
   }
    return 0;
}
  • 进行指针的初识化
  • 指针使用之前检查有效性
  • 避免数组越界
  • 指针指向空间释放即使置NULL

指针的运算

指针减指针的运算

举一个简单的例子看一下指针-指针的运算:

int main() {
	int a[10] = { 1,2,3,4,5,6,7,8,9,0 };
	printf("%d\n", &a[9] - &a[0]);
	printf("%d", &a[0] - &a[9]);

	return 0;
}

运行上面的代码;运行结果如图:

运行图
而&a[9]和&a[0]之间的指针内存空间画图所示

在这里插入图片描述

可以得出:指针-指针的结果的绝对值是指针和指针之间的元素个数。

**注意:**指针-指针的用法的前提是两个指针指向同一片区域。

  • 指针-指针实际运用
    一般我们模拟实现strlen()函数的用法:
#include<stdio.h>
int myStrlen(char *s) {
	int count = 0;
	while (*s != '\0') {
		count++;
		s++;
	}
	return count;
}
int main() {
	char ch[] = "abcdefgh";
	int len = myStrlen(ch);
	printf("%d", len);

	return 0;
}

而利用指针-指针的方法可以是:

#include<stdio.h>
int myStrlen(char *s) {
	//int count = 0;
	int *start=s;
	while (*s != '\0') {
		//count++;
		s++;
	}
	return s-start;
}
int main() {
	char ch[] = "abcdefgh";
	int len = myStrlen(ch);
	printf("%d", len);

	return 0;
}

指针与数组

首先我们举一个简单的例子:

#include<stdio.h>
int main() {
	int a[10] = { 1,2,3,4,5,6,7,8,9,0 };
	printf("%p\n", a);
	printf("%p\n", &a[0]);

	return 0;
}

运行结果可以看的出**a,&a[0]**都是得到的同一个内存空间地址。
结论:数组名表示的是数组首元素的地址。

但是有2个例外:

  1. sizeof(数组名)–这里的数组名不是首元素的地址,是表示整个数组的,这里计算的是整个数组的大小,单位还是字节
  2. &数组名–这里的数组名不是首元素的地址,是表示整个数组的,拿到的是这个数组的地址
    那我们就要验证一下吧:
#include<stdio.h>
int main() {
	int a[10] = { 0 };

	printf("%p\n", a);//数组名是首元素的地址
	printf("%p\n", a+1);
	printf("\n");
	printf("%p\n", &a[0]);//第一个元素的地址
	printf("%p\n", &a[0]+1);
	printf("\n");
	printf("%p\n", &a);//整个数组的地址
	printf("%p\n", &a+1);


	return 0;
}

运行结果如图:
运行图
结果显而易见,&a是取的整个数组的地址,其余都是取的数组元素的第一个元素的地址。

觉得内容还不错的小伙伴们,麻烦留下自己的足迹哦!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值