玩指针

指针作为C/C++的灵魂,其可玩性可以说是相当不错的。

指 float 为 int

#include <bits/stdc++.h>
using namespace std;

int main(int argc, char const *argv[]){
	float a = 20.59375;
	int *p = (int *)&a;
	// int *p = reinterpret_cast<int*>(&a); // c++ 一般采用这种写法,效果一样
	cout << (*p) << endl;
	return 0;
}

输出

1101316096

1101316096是个啥?
我们来看看它的二进制形式:

#include <bits/stdc++.h>
using namespace std;

int main(int argc, char const *argv[]){
	float a = 20.59375;
	int *p = (int *)&a;
	cout << (*p) << endl;
	cout << bitset<32>(*p) << endl;
	return 0;
}

输出

1101316096
01000001101001001100000000000000

我们发现它就是20.59375IEEE754格式(理所当然):

在这里插入图片描述

原理

初学时我们说变量是一个盒子,其实变量代表一块内存空间,里面存着很多0或1。

我们通过取址(&)拿到变量a这块内存空间的地址,a是一个float的变量,&a自然是一个float的地址,但是我们“骗”计算机说这是一个int的地址,再通过取值(*)得到了1101316096,在这过程中,内存里其实并没有改变(始终是01000001101001001100000000000000),只是我们看待这块内存的方式变了,所以数字也就从20.59375变成了1101316096。

所以,指针可以强制改变“看待某段内存的方式”,你说这段内存是啥它就是啥

同理:

1852076899 是 ‘csdn’?

#include <bits/stdc++.h>
using namespace std;

int main(int argc, char const *argv[]){

	int a = 1852076899;

	cout << bitset<32>(a) << endl;

	printf("%d\n", a);

	printf("%f\n", *(float*)&a);

	for (int i=0; i<4; i++){
		putchar(((char*)&a)[i]);
	}

	return 0;

}

输出

01101110011001000111001101100011
1852076899
17675519055701040529804361728.000000
csdn

ascii码对照:
csdn
为什么反了?详见内存中的整数

让我们来玩儿点花的

#include <bits/stdc++.h>
using namespace std;

void to_charArr(){
	char *p = (char*)&cin;
	for (int i = 0; i < sizeof(cin); ++i,i%16||putchar('\n')){
		printf("%d,\t", *p);
		p++;
	}
	cout << endl;
}

int main(int argc, char const *argv[]){
	to_charArr();
	char s[] = {
		88,     12,     73,     0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
		-128,   12,     73,     0,      0,      0,      0,      0,      6,      0,      0,      0,      0,      0,      0,      0,
		0,      0,      0,      0,      0,      0,      0,      0,      2,      16,     0,      0,      0,      0,      0,      0,
		0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
		0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
		0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
		0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
		0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
		0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
		0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
		0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
		0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
		0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
		8,      0,      0,      0,      0,      0,      0,      0,      -112,   102,    72,     0,      0,      0,      0,      0,
		96,     73,     72,     0,      0,      0,      0,      0,      0,      106,    72,     0,      0,      0,      0,      0,
		0,      0,      0,      0,      0,      0,      0,      0,      -64,    90,     72,     0,      0,      0,      0,      0,
		-64,    81,     72,     0,      0,      0,      0,      0,      48,     90,     72,     0,      0,      0,      0,      0,
		16,     90,     72,     0,      0,      0,      0,      0
	};

	istream *ccin = (istream*)(&s);
	string x;
	(*ccin) >> x;
	cout << x << endl;
	return 0;

}

我们让一个istream指针ccin指向一个字符数组,告诉它“没错,这就是个istream”,这个ccin同样能当cin用。

当然,这段代码大概率是没法在其他电脑上正常运行的,因为cin内部在不同的机器上会有不同的样子,这个数组s[]需要手动改成控制台上输出的那个数组。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值