指针初阶1

指针

1.什么是指针

1.1内存空间是通过单个的内存单元管理,指针是内存中最小单元的编号,即地址,通过内存单元编号可以找到对应的值,也被称为地址(指针)。接下来我们来看一下地址的表示形式是什么:

int main()
{
    int a = 10;
    printf("%p",&a);//打印地址用%p
    return 0;
}

运行结果如下:

0x00dbfd98

我们发现打印出的地址是一个16进制的数字,但一个int类型所占内存空间大小为4个字节,每个内存单元都有不同的编号(地址),所以

这当中的0x00dbfd98即为第一个内存编号,通过第一个编号可以找到后面的编号。

1.2什么是指针变量

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

在上述代码中我们用p来存放a的地址,其数据类型为整形指针

1.3总结:指针即为地址,平常说说的指针即为指针变量,用来存放内存地址的变量内存是由内存单元组成,每个内存单元占一个字节,比如int类型占4个字节,也就是说占4个内存单元大小。其中每个内存单元都有地址,也就是编号,即指针,通过指针可以找到该内存单元。

2.指针和指针类型

指针类型的意义

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

指针类型决定了指针被解引用时可以访问字节的数量,上述代码指针类型被强制转换为char*类型,char是占用一个字节,而int占4个字节,所以当被强制类型转换时,访问权限发生改变,只能访问一个字节

int main()
{
    int a = 0x11223344;
    int* pa = &a;
    int* pc = (char*)&a;
    
    printf("pa=%p\n",pa);
    printf("pa+1=%p\n",pa+1);
    
    printf("pc=%p\n",pc);
    printf("pc+1=%p\n",pc+1);
    return 0;
}
//结果
//pa=00AFF9BC
//pa+1=00AFF9C0
//pc=00AFF9BC
//pc+1=00AFF9BD

指针类型决定了指针+1/-1操作的时,跳过几个字节(决定指针步长)

3.野指针

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

野指针成因
  • 指针未初始化
int main()
{
    int* p;//p没有初始化,没有明确指向
    //一个局部变量没有初始化,放的是随机值:0xccccc
    *p=10;
    return 0;
}
//这里的p就是野指针,因为改指针未初始化,指向的位置是随机的
  • 指针访问越界
int main()
{
    int arr[10]={0};
    int *p =arr;//&arr[0]
    int i=0;
    for(i=0;i<=10;i++)
    {
        *p=i;
        p++;
    }
    return 0;
}
//当p指向超出arr数组范围,会出现野指针问题
  • 函数释放空间
int* fun()
{
    int a = 10;
    int* p = &a;
    return p;
}
int main()
{
    int* p = fun();
    return 0;
}
//当函数访问结束后内存空间会被销毁,a所指向的地址虽说被存在p指针当中,但是p指针不能被指向一个确定的值
如何避免出现野指针
int main()
{
    int a = 10;
    int *p = &a;//明确给指针初始化
    int* p2 = NULL;//初始化空指针,NULL相当于0
    if(p2!=NULL)//当p2指向的不为空就可以进行解引用
    {
        *p2 = 100;
    }
    return 0;
}

4.指针运算

  • 指针±整数
#define N
float values[N];
float *vp;
for(vp=values[0];vp<values[N];)
{
    *vp++=0;
    //*vp=0 -> vp++
}

数组赋值的一些指针写法

int main()
{
    int arr[10];
    int* p = &arr;
    int sz = sizeof(arr)/sizeof(arr[0]);
    for(int i=0;i<sz;i++)
    {
        //*p = 1;
        //p++;
        *(p+1) = 1;
    }
    return 0;
}

指针-指针

int main()
{
    int arr[10]={0};
    printf("%d",&arr[9]-&arr[0]);
    return 0;
}
//运行结果:9

|指针-指针| 得到的是指针和指针之间元素的个数

不是所有指针都能相减,指向同一块空间的2个指针才能相减,才有意义

应用

int fun(char* str)
{
    char* start = str;
    while(*str!='\0')
    {
        str++;
    }
    return (str-start);
}
int main()
{
    char ch[10]="abcdefg";
    int len = fun(ch);
    printf("%d",len);
    return 0;
}

5.指针和数组

int main()
{
	int arr[10];
	int sz = sizeof(arr) / sizeof(arr[0]);
	int* p = arr;
	for (int i = 0; i < sz; i++)
	{
		printf("\n%p\n%p", &arr[i], p + i);
	}
	return 0;
}
//运行结果
0000000C82F9F518
0000000C82F9F518
0000000C82F9F51C
0000000C82F9F51C
0000000C82F9F520
0000000C82F9F520
0000000C82F9F524
0000000C82F9F524
0000000C82F9F528
0000000C82F9F528
0000000C82F9F52C
0000000C82F9F52C
0000000C82F9F530
0000000C82F9F530
0000000C82F9F534
0000000C82F9F534
0000000C82F9F538
0000000C82F9F538
0000000C82F9F53C
0000000C82F9F53C

通过上述代码可知指针p和&arr[i]所指向的地址一样,因为数组名是首元素地址,而我们先前通过int *p = arr,把地址赋值给指针变量p,

实际上arr[i]->*(arr+i)

6.二级指针

用来存放一级指针变量的地址

int main()
{
	int a = 10;
	int* pa = &a;//pa是一个指针变量,一级指针变量,1次解引用就可以找到a
	int** ppa = &pa;//ppa是一个二级指针变量,存放指针变量pa的地址
	**ppa = 20;
	//*pa = 20;
	printf("%d ", a);

	return 0;
}
//*pa 代表pa是指针,int代表pa指向的类型
//所以*ppa代表的是指针,指向类型为int* ,即写成int* *ppa;

7.指针数组

含义:存放指针的数组

int main()
{
	int a = 10;
	int b = 10;
	int c = 10;

	int* pa = &a;
	int* pb = &b;
	int* pc = &c;

	int* arr[3] = { pa,pb,pc };
    //arr就是存放指针的数字-》指针数组
    for(i=0;i<3;i++)
		printf("%d\n", *arr[i]);
	return 0;
}

一维数组关联成二维数组

int main()
{
	int a1[4] = { 1,2,3,4 };
	int a2[4] = { 2,3,4,5 };
	int a3[4] = { 3,4,5,6 };
	int* pa[3] = { &a1,&a2,&a3 };
	int i;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 4; j++)
		{
			printf("%d ", *(pa[i] + j));
			//printf("%d ", pa[i][j]);  arr[i]==*(arr+i)
		}
		printf("\n");
	}
	return 0;
}
  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值