我总结的三个内存相关结论:
结论1: int addr变量的值和地址是完全不同的两个东西!
结论2: 内存地址的获取必须使用取地址&操作符或malloc/new等方式
结论3: 请使用机器相关的size_t来表示内存取值范围
具体如下:
在windows中做测试,你会发现:
我们来分析一下 int addr=0x100000这句话的含义:
当我们声明了 int addr,编译器就知道要在栈内(不是堆哦)分配一个4 byte(在x86和x64中,sizeof(int) = 4byte)的变量addr。
当我们进行赋值时,addr = 0x100000,那么该变量对应的值为0x1000000.
实际上该变量还有地址,如何获取呢?
通过取地址操作符&来获取:
你会发现addr的值=0x100000,而addr的地址=0x00cff700
结论1: int addr变量的值和地址是完全不同的两个东西!
那么为什么0x100000和0x00cff700类型相同,看起来区别不大,但是(int)addr却报错呢?
这是因为windows中(其他操作系统也应该类似)是虚拟内存地址映射,而且内存地址的区间是有规定范围的,并不是你能直接声明获取的。
这个内存区间,并不是你能够直接赋值控制的。
在c/c++中,你只能通过两种方式来获取地址:
a. 如上所述,通过取地址操作符&来获取栈分配的变量的地址
b. 使用c语言中的malloc等内存分配函数或c++中new操作符后返回的指针(地址)
b中的malloc内部调用的是windows 系统api,而c++调用的是c语言的malloc函数。
由此可见,实际上,在操作系统层面,你根本无法直接操作硬件,而是必须要调用操作系统提供的api才能进行所有的系统操作。操作系统才是上帝!(这也是dos时代的程序员对windows最大的抱怨,无法直接控制硬件,必须通过间接方式。)
至于其他系统(除了嵌入式)都是无法直接控制硬件,必须要使用操作系统提供的api才可以!
int addr = 0x100000;
int* pAddr = &(addr);
//int ret = *(int *)addr;
int ret = pAddr; //通过方式,从地址获取对应的值
printf("%d\n", addr == ret); //返回1,true
结论2: 内存地址的获取必须使用取地址&操作符或malloc/new等方式
实际上用int来表示指针取值范围非常可怕,因为在32位和64位系统上,很多系统sizeof(int)都等于4byte,意味着在64位系统上,无法表示完全的指针取值范围。
请使用size_t来表示地址取值范围,保证无误.
结论3: 请使用机器相关的size_t来表示内存取值范围
附sizeof各个平台下基础数据类型的字节长度:(本人花了不少时间测试所得)
我曾经写过几篇相关的文章,提供一下url以供参考吧!
闲聊c/c++: 各平台下基本数据类型的字节长度
http://www.jianshu.com/p/1116616940bb
闲聊c/c++: size_t、ptrdiff_t、socklen_t数据类型
http://www.jianshu.com/p/51347fcf539c
闲聊c/c++: 谈内存(大/小端,高/低字节,高/低地址)
http://www.jianshu.com/p/c41741b5c19d
闲聊c/c++: 再谈内存(c/c++,java,c#,js,objc中的大小端以及装箱拆箱和统一类型系统)
http://www.jianshu.com/p/1367009a3fce
青衫磊落险峰行
2017-9-19 0:13
网友评论