指针笔记(待补充)

视频链接:十年程序员整理的指针教程 | 没有废话 直奔主题 彻底搞懂指针 | 可以白嫖_哔哩哔哩_bilibilii

一. 指针的基本概念

int a=1;

int* p=&a;

p的类型是int* 类型,叫整型指针类型   p是一个指针变量

&表示取地址,&a则表示a这个变量的地址

int* p=&a; 表示把a的地址保存在了变量p中

注:1个字节占8个二进制位

64位操作系统中指针变量通常是占8个字节(64/8=8)

32位操作系统中指针变量通常是占4个字节(32/8=4)

测试:

#include <stdio.h>
#include<stdlib.h>
int main()
{
  //sizeof 用来计算给定类型或变量的大小 以字节为单位
	printf("int* 类型指针变量大小为:%d\n", sizeof(int*));
	printf("int 类型变量大小为:%d\n", sizeof(int));
	printf("short* 类型指针变量大小为:%d\n", sizeof(short*));
	printf("short 类型指针变量大小为:%d\n", sizeof(short));
	printf("long* 类型指针变量大小为:%d\n", sizeof(long*));
	printf("long 类型指针变量大小为:%d\n", sizeof(long));
	printf("char* 类型指针变量大小为:%d\n", sizeof(char*));
	printf("char 类型指针变量大小为:%d\n", sizeof(char));
	printf("float* 类型指针变量大小为:%d\n", sizeof(float*));
	printf("float 类型指针变量大小为:%d\n", sizeof(float));
	printf("double* 类型指针变量大小为:%d\n", sizeof(double*));
	printf("double 类型指针变量大小为:%d\n", sizeof(double));
	system("pause");
	return 0;
}

输出:

我这上面显示的都是4个字节

占多少字节看系统是多少位的

#include <stdio.h>
#include<stdlib.h>
int main()
{
	int a = 1;
	int* p = &a;
	printf("a的地址为:\n");
	printf("%p", &a);
	printf("\n");
	printf("指针变量p变量所存储的地址 或是p所指向的地址:\n");
	printf("%p", p);//%p输出地址 打印指针变量的内存地址
	printf("\n");
	printf("指针的大小为%d个字节", sizeof(p));
	system("pause");
	return 0;
}

输出:

006FF784 这8个数字每个数字是十六进制数 每个用4位二进制表示 

8位二进制是一个字节 所以是4个字节表示一个地址

指针示意图:

注意:* 的两种含义

1.定义的时候 (前面有类型):

   比如 int* ,int和*可以理解为构成了一个整体

   表示后面的变量是指针   如int* p=&a;

2. 使用的时候(前面没有类型):

   表示取值(取指针指向的内存空间的值)

   int* p=&a;

      *p=100;//这里的*p可以理解为就是变量a,即把a改为100

区别:int* 和char*的区别

char ch=‘a’;

char* q=&ch;

     int* 和char* 都作为指针变量(但一个是整型指针变量,一个是字符型指针变量),他们的长度是一样的,但是它们指向的整型变量和字符型变量长度是不一样的

    而且int* 和 char*的步长是不一样的

#include <stdio.h>
#include<stdlib.h>
int main()
{
	int num = 1;
	int* p = &num;
	*p = 100;
	printf("整数的值为%d\n", num);
	printf("整型指针变量的地址为:%p\n", p);
	printf("整型指针变量+1后的地址为:%p\n", p + 1);

	char ch = 'a';
	//int* q = &ch;//会报错 类型对不上 什么变量类型就对什么变量类型指针
	char* q = &ch;
	*q = 'x';
	printf("字符的值为%c\n", ch);
	printf("字符型指针变量的地址为:%p\n", q);
	printf("字符型指针变量+1后的地址为:%p\n", q + 1);
	system("pause");
	return 0;
}

结果:

整型指针变量+1 , 整数占4个字节,地址实际上+4

字符型指针变量+1 ,字符占1个字节,地址实际上+1

指针变量的步长取决于其所指向的变量类型

但实际上可以这么理解:

整型指针+1,它指向了下一个整型

字符型同理 指针+1,指向了下一个字符

二. 指针作为函数参数

最典型的例子 两个数互换值

#include <stdio.h>
#include<stdlib.h>
void swap(int x,int y)
{
	int t = x;
	x = y;
	y = t;
	
}
int main()
{
	int a = 1, b = 2;
	swap(a, b);
	printf("互换后 a的值为%d\n", a);
	printf("互换后 b的值为%d\n", b);
	system("pause");
	return 0;
}

结果:

a和b的值并没有得到交换

实参a,b分别传值给了函数中的形参 x,y

而在函数中,x,y执行了相关的互换操作之后,函数调用结束后形参被释放了

而a,b仍是保留了原值

如果要交换实参的值,必须要传地址

#include <stdio.h>
#include<stdlib.h>
void swap(int* x,int* y)
{
	int t = *x;
	*x = *y;
	*y = t;
	
}
int main()
{
	int a = 1, b = 2;
	swap(&a, &b);
	printf("互换后 a的值为%d\n", a);
	printf("互换后 b的值为%d\n", b);
	system("pause");
	return 0;
}

结果:

这次互换成功了 

swap(&a, &b); 将a的地址b的地址传入函数

void swap(int* x,int* y) 交换函数用x,y两个整型指针变量接收传入的地址

而在函数内 *x ,*y就是将x,y指向的数据进行操作,也即a,b

函数执行结束后形指针类型变量x,y虽然释放,但a,b的值也进行了实际上的交换

再次注意:如果要交换实参的值,必须要传地址

同时,传参用指针效率也往往更高,比如结构体,传入整个结构体数据很大,但传入它的地址,用指针接收,也有着相同的效果,而且指针的字节数往往是固定的

三.  指针的运算

int a,*pa=&a,*pb;pb=pa;

这句代码意思是定义一个整型变量a,又有int* pb=&a  (*pa=&a要与前面的int连起来看)

即a的地址赋给了pb,又创建了一个整型指针pb,第二个语句中,指针pa直接赋值给了pb,这两个指针此时指向同一个地方 即a

下面来看几个运算:

#include <stdio.h>
#include<stdlib.h>
int main()
{
	int x = 3, y = 0, * px = &x;
	y = *px + 5;
	printf("y的值为:%d\n", y);
	system("pause");
}

y的值为-------8

很明白,实际上就是px所指向的x加上3然后赋值给了8

#include <stdio.h>
#include<stdlib.h>
int main()
{
	int x = 3, y = 0, * px = &x;
	y = ++ * px;
	printf("y的值为:%d\n", y);
	system("pause");
}

y的值为------4

这也没有非议 px所指向的x先进行自增,3+1=4然后赋值给了y

y = ++ (* px); 在*px外面加个括号是一个意思

下面这两个例子注意区别:*px++ 和(*px)++的区别

第一个

#include <stdio.h>
#include<stdlib.h>
int main()
{
	int x = 3, y = 0, * px = &x;
	y = *px++;//不加括号
	printf("y的值为:%d\n", y);
	system("pause");
}

先把px指向的x的值赋值给了y 

y的值为:3

下一步是谁++?是px+1 ,px的地址增加了4个字节,可以理解为px指向下一个整型变量

y = (*px)++;//加括号

而这个表示的是*px赋值给y  后,*px加一 即x的值加1

附加:const相关事宜

const讲究一个就近原则,表示指向的东西不能改

如过作形参希望某个参数不能被修改可以在前面加上const

比如 void mystrcpy(char *dest,const char* scr)

const的不可被修改指的到底是谁?

const int *p1=&num;

就近 离他最近的数据是*  他指的是*p1不可被修改

(*p1)++ 会报错 即num不可被修改、

而p1++ 没问题,p1本身可以被修改

int* const p2=&num;

离他最近的数据是p2

p2++报错 p2不可以被修改

而(*p2)++可以 

const int * const p3=&num;

(*p3)++不行

p3++也不行

四. 空指针和野指针

#include <stdio.h>
#include<stdlib.h>
int main()
{
	int* p;
	*p = 100;
	system("pause");
}

这个代码跑不过,p是野指针,只定义了p是一个整型指针 ,然而它指向哪里呢

对*p强行改值有很大风险

#include <stdio.h>
#include<stdlib.h>
int main()
{
	int* p=NULL;
	*p = 100;
	system("pause");
}

 初始赋值为null使其为空指针也没用,跑了会报错,难道它改的是空地址地方的值吗

但相较于野指针,空指针还是要好一点,他不会破坏不知道什么地方的数据

如何合法地使用内存呢?

1.系统分配的内存

int a;

int *p1=&a;

这种是操作系统自己分配的

2.用户申请内存(堆内存) 注意规范

char *str=(char*)malloc(32);//动态开辟一个32字节大小的内存,并把起始地址赋值给指针str

free(str);//释放str指向的堆内存,如果不释放,内存越用越少,会造成内存泄露

str=NULL;//将str赋值为空指针,不能让其成为野指针

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值