详解C语言中的取值运算符

* 的几种用途

  1. 乘法运算符
int x = 1;
int y = 2;
int z = x*y;
  1. 定义新的类型
char x;
char* x1;
char** x2;
  1. 取值运算符
格式:
* + 指针类型的变量
int* a = (int*)1;
printf("%x \n",*a);

这里举一个例子分析一下:

#include <stdio.h>					//头文件
#include <windows.h>

void main()							//程序入口
{
	int* a = (int*)1;				//定义一个值为1的指针类型a

	printf("%x \n",*(a+1));			//把这个指针类型+1的地址里的值打印到控制台

	return;							//程序结束
}

这个程序运行是会报错的:
在这里插入图片描述

原因很简单,我们去反汇编看一下问题出在哪里:
在这里插入图片描述

这是它的汇编指令,我们简单分析一下:

00401028   mov         dword ptr [ebp-4],1			//把1赋值给ebp-4,也就是第一个变量
0040102F   mov         eax,dword ptr [ebp-4]		//把ebp-4的值存到eax里
00401032   mov         ecx,dword ptr [eax+4]		//这里出问题了,把eax+4这个地址里的值取出来存到ecx里
00401035   push        ecx							//ecx压栈
00401036   push        offset string "%x \n" (0042201c) 	//压入字符串
0040103B   call        printf (00401070)			//调用printf()函数输出结果
00401040   add         esp,8						//平衡堆栈

很明显,eax+4的地址就是0x00000005,这个地址是不存在的,所以程序会报错,这里对应的就是这行代码:

pinrf("%x \n",*(a+1));

这里的a+1并不是真的+1,在反汇编中也看到了,是+4,原因就是指针变量加减的多少,取决于去掉* 以后的数据类型的宽度是多少,这里是int,自然就+4,如果是a+2,那就是+8了。

探测 *指针类型 的类型

这个标题可能有点绕,意思就是看一下当编译器遇到赋值操作的时候是怎么处理的,看一下这个例子:

#include <stdio.h>
#include <windows.h>

int*** a;
int*** b;
int*** c;

void mian()
{
	int x = *(a);
	return;
}

看一下它的报错:
在这里插入图片描述这里的int自认就是int x,那这个int就是我们定义的指针int* a,编译器在这里把int*** a当作了int**类型来处理,在原先的基础上减少了一个*,那我们定义五个 *来验证一下:

#include <stdio.h>
#include <windows.h>

int***** a;
int*** b;
int*** c;

void mian()
{
	int x = *(a);
	return;
}

看一下报错,跟我们推断的一样:
在这里插入图片描述
如果代码是这样就不会报错了:

int* a;
void main()
{
	int x = *(a);
	return;
}

总结:*加上一个指针类型如 *(a) ,结果的类型就是原来的指针类型减去一个 *。

取值运算举例

这里这两个例子注释的已经比较详细了,这里就不过多分析,感兴趣的可以自己去看一下反汇编,并不难理解。

例1:

#include <stdio.h>					//头文件
#include <windows.h>

void mian()							//入口函数
{
	int x = 1;						//把1赋值给x
	int* p = &x;					//把x的地址赋值给p

	printf("%x %x\n",p,*(p));		//以16进制输出x的地址与x的值

	*(p) = 2;						//把p指向的内存的值改为2,也就是x的值
	printf("%d \n",x);				//输出x的值

	return;							//程序结束
}

例2:

#include <stdio.h>				//头文件
#include <windows.h>


int x = 1;						//把1赋值给x

void mian()						//程序入口
{
	int* p = &x;				//把x的地址存到p里
	int** p2 = &p;				//把p的地址存到p2里
	int*** p3 = &p2				//把p2的地址存到p3里

	int r = *(*(*(p3)));		//把x的值赋给r,第一层输出p2,第二层输出p,第三层输出x(这里都是把指针变量当作地址,取地址里的值,与上面的嵌套一一对应)
	printf("%d \n",r);			//输出r

	return;						//程序结束
}

发布了69 篇原创文章 · 获赞 81 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_43573676/article/details/105332441