指针理解(1)

什么是地址?

1.在这儿我想从硬件的角度来解释地址是什么?1
看上图,在计算机中,CPU(一块芯片)与内存(一块或几块芯片)是通过导线来连接的,在者之间,有三组总线,数组总选,负责数据的运输,控制总线,负责读数据写数组,那么在这儿呢,我们要关心的就是地址总线,它是为了管理内存单元,编址所用的总线,一个内存单元有8位,是8根数据线所连接的,如果要访问一个内存单元,则必须要有对应的地址,通过地址,来找到内存单元,对所指定的内存进行操作,那么地址总线的多少则决定了地址编码范围有多大,决定了内存空间有多大!
比如x86的机子,则有32根地址线,它所管理的内存单元有2^32个内存单元,
x64的机子,则有64根地址线,它所管理的内存单元有2^64个内存单元,明显,
位数越多,管理的内存越大!!!

地址,指针,指针变量的关系

 (1)地址就是地址,就是内存空间单元的编号!
 (2)指针就是地址,没什么区别,只是叫法不一样!
 (3)指针变量的本质是变量,是在内存中占用的一小块空间,一般而言是(局部变量)在栈区开辟的一块空间,这块空间是放地址编号的!它也是有地址的!

对指针变量的理解

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

 上面代码很简单,创建了变量a,把a的地址存放到指针变量pa中,这儿怎么理解int*pa;?
1
 #这儿int * pa = &a,*表明了变量pa是个指针变量,int 则表明了这是个指向int的指针变量!

指针变量的大小

#很简单,指针变量是存地址的,地址有多少位,则开辟的指针变量有多大?32位机器上—>4个字节,64位机器上—>8个字节,在这儿说一下,指针的大小跟指针类型一点关系没有,它是个编码,有什么关系!!!

int main()
{
	printf("%zd\n", sizeof(char*));
	printf("%zd\n", sizeof(short*));
	printf("%zd\n", sizeof(int*));
	printf("%zd\n", sizeof(double*));
	return 0;
}

1

指针类型的意义

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

调试这段代码!!!
1
1
从上面可以看,int * 的指针执行完*pa = 0之后,a的每个字节被改成0了!

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

调试这段代码!!!
1
从上面可以看,char的指针执行完pa = 0之后,a的第一个字节被改成0了,其它不变!

结论:指针类型的大小决定在解引用访问内存的时候,访问多大的空间,这个也能理解,比如int*的指针,对应的就int类型的变量,为所改变他在内存中的值量身打造!!!

int main()
{
	int a = 10;
	int* pa = &a;
	char* pc =(char*)&a;
	printf("pa = %p\n", pa);
	printf("pc = %p\n", pc);

	printf("pa+1 = %p\n", pa + 1);
	printf("pc+1 = %p\n", pc + 1);
	return 0;
}

1
 我们可以看出,char* 类型的指针变量+1跳过1个字节,int* 类型的指针变量+1跳过了4个字节。
这就是指针变量的类型差异带来的变化。
结论:指针的类型决定了指针向前或者向后⾛⼀步有多⼤(距离)。

void*指针

 void*指针是一种无具体类型的指针,这个指针非常重要,它可以接受任何类型的指针,由于它自己没有什么特定的类型,所以他不能解引用操作,也不能进行指针的运算!!!

int main()
{
	int a = 10;
	//int* pa = &a;
	//char* pc = &a; //warning
	void* pv = &a;
	*pv = 10;//err
	pv++;  //不能加
	//void* 就是存储不同类型的地址

	return 0;
}

1

const关键字

int main()
{
	const int a = 10; //a不能被修改了,但是a的本质还是变量,const仅仅是在语法上做了限制,所以我们习惯上叫a是常变量
	//a = 20;  //修改报错
	printf("a  = %d\n", a);
	return 0;
}

 *变量a被const修饰之后,不能修改a的值了,这是因为c语言在设计的时候在语法层面做了限制,a的本质还是变量,怎么证明?看看反汇编就知道!!!

const int a = 10;
mov         dword ptr [ebp-8],0Ah
//对应的汇编代码还是这样,10装进了ebp-8的地质单元中,没有任何修改!!!

 const修饰指针,看下面代码!!!

int main()
{
	const int a = 10;
	const int* p = &a;  //限制的是*p
	int* const p = &a;    //限制的是p
	//const放在*的左边,限制的是*p,意思是不能指针变量p修改p指向的内容
    //const放在*的右边,限制的是p变量,也就是p变量不能被修改了,没办法在指向其它变量了
	*p = 0; //err
	printf("%d\n", a);
	return 0;
}

*这儿呢?在语法层面是这样限制的!
*const int * p; 或int const * p;在这儿const关键字限制的是 * p,也就是p所指向的空间内容不让修改;
#int * const p;const限制的是p变量,p里面的内容不让修改!!!

指针运算

1)指针±运算
 这个也很简单,指针+1操作就是跳过1个指针类型的大小,来到下一个单元的地址.
 下面是一个通过指针访问数组的例子,很简但!!!

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	const int* p = &arr[0];
	for (int i = 0; i < 10; i++)
	{
		//printf("%d ", *p);
		//p++;
		printf("%d ", *(p + i));
	}
	return 0;
}

2)指针-指针的运算

int  my_strlen(const char* str)
{
	char* start = str;
	char* end = str;
	while (*end++);
	return end - start - 1;
}
int main()
{
	int len = my_strlen("abc");
	printf("%d", len);
	return 0;
}

指针-指针的绝对值得到的是两个指针之间的元素!!!
 指针-指针的前提是两个指针指向同一块空间!!!
 刚才想了一下,如果是两个不同的类型的指针相减呢?

int main()
{
	int arr[] = { 0,1,2,3,4,5,6,7,8,9 };

	int* start = &arr[0];
	char* end = (char*)&arr[1];
	printf("%d\n", end - start); //4
	//char* - int* 转化成了char*来减
	char* start1 = (char*)&arr[0];
	int* end1 = &arr[1];
	printf("%d\n", end1 - start1);//1
	//int* - char*转化成了int*来减
	char* start2 = (char*)&arr[0];
	char* end2 = (char*)&arr[1];
	printf("%d\n", end2 - start2);//4

	int* start3 = &arr[0];
	int* end3 = &arr[1];
	printf("%d\n", end1 - start1);//1

	return 0;
}

上面的例子我不确定,结果是在vs2022下测试的结果!有时间了,查看汇编代码,看看具体怎么执行!!!
3)指针的关系运算
 这个也没多大作用!!!(这个其实就是地址大小的比较)

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(int);
	int* p = arr;
	//arr是数组名,数组名其实是数组首元素的地址
	while (p<arr+sz) {
		printf("%d ", *p);
		p++;
	}
	return 0;
}

完结!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值