本文目录一览:
C语言和内存关系
恩,不错,可以这么说。
软件是怎么到内存并运行的呢?这个内存地址有何关系呢?
就拿任何一个windows程序来说,程序的入口点都是WinMain,这个WinMain在内存的什么地方呢?
在win7之前,只要你不修改链接器选项,这个WinMain一定是在内存的0X400000.
任何程序都需要操作系统内核支持,操作系统的内核的地址是0X80000000~4GB之间。
其他的库文件,比如C语言中支持字符串函数(如strcap)的库在400000与80000000之间。
可见,硬盘上的exe文件在进入内存之前,就已经明确知道自己会在内存的什么位置。
当然,这里有个4GB虚拟地址空间的概念:在32位系统中,系统为每个exe文件分配了一个4GB的虚拟空间,无论你是否安了4G内存。很显然,很多库,特别是系统内核,都是能共用的,所以你的系统能同时运行多个需要4GB虚拟空间的程序。
这个和C语言的指针有何关系呢?
举个简单例子:每个exe文件一般需要系统的dll文件才能运行,在exe文件的开头,有一个表记录了该exe需要那个dll中的哪个函数。由于dll地址是固定的,函数地址为相对于该dll地址的偏移地址,所以exe能在4GB空间中找到它需要的函数。你可以通过exe文件的基地址找到这个表,这个基地址在每个程序运行时由系统交给了exe程序,这个基地址就是一个指针。然后你能修改这个指针,所以以后每次调用这个函数时,程序将转跳到你自己的代码中。这其实就是c语言中的函数指针的概念。
在汇编语言中是没有指针的,因为指针本质上就是内存中的地址。exe文件和dll文件中各种基地址和偏移地址,就是你所说的“无数个指针”。
当然,以上解释是非常浅薄的,指针、内存、地址的概念是简单的,但在实际的系统中却非常复杂。如果你想了解一些底层的,本质的问题,可以在学习C语言之后参考一些汇编语言,windows底层编程等书籍,比如《Windows via C/C++ 第五版》《Intel汇编语言程序设计 第五版》就是两本很好的入门教程。
C语言高低位互换操作
在看图形处理源码的时候有一段宏看不懂,就写了一个demo自己看了一下。
还是不大熟悉C语言的位操作。
这个宏挺有意思
注意 括号的位置很重要
((const uint8_t*)(x)) 这相当于把x所在的内存当做一段uint8类型的指针,索引x的第0位,因为是小端机,低位存低字节,所以[0]位存的是低字节,[1]位存的是高字节。
这样想的话,这个宏其实很简单了,就是把16位的无符号数,按照8位一个单位高低位互换
事实也证明如此,程序输出如下
“c语言允许直接访问物理地址,能进行位操作”是什么意思啊
就是使用C语言能够直接定位物理内存的地址,即通过内存地址(如0xfa283401)得到该地址上的数据。
计算机中的数据都是以位(bit,比特)来作为基本单位的,C语言能直接对位进行操作,包括求与,并,或,异或,非等。
物理地址是一个很宽泛的概念,磁盘,内存等存储设备都有物理地址的说法。
物理内存地址指的是硬件实现上物理内存展现给外部总线访问的编码地址,其范围等于物理内存的大小.
大家常说的物理内存就是指安装在主板上的内存条,其实不然,在计算机的系统中,物理内存不仅包括装在主板上的内存条(RAM),还应该包括主板BIOS芯片的ROM,显卡上的显存(RAM)和BIOS(ROM),以及各种PCI、PCI-E设备上的RAM和ROM。
地址空间就是对物理内存编码(地址编码)的范围。
所谓编码就是对每一个物理存储单元(一个字节)分配一个唯一的地址号码,这个过程又叫做“编址”或者“地址映射”。这个过程就好像在日常生活中我们给每家每户分配一个地址门牌号。与编码相对应的是“寻址”过程——分配一个地址号码给一个存储单元的目的是为了便于找到它,完成数据的读写,这就是“寻址”,因此地址空间有时候又被称作“寻址空间”。系统不仅要给主板上的内存条编址,还要给上述的其它物理内存编址;它们都被编在同一个地址空间内,编址后的物理内存就可以被系统资源使用或占用。
C语言的小问题,涉及内存、地址、位操作等。高手进。
C语言中对指针(地址)进行加减1的操作只能让你移动到下一个或上一个存储单元,而不能让你移动一个二进制位,具体这个移动量是几个字节,这是由指针的类型决定的。
也就是说,在这个程序中,p是指向int型的指针(你所在操作系统规定int型为4字节,也就是32位二进制位),因此p+1就往后挪了32个二进制位,而不是你想象的1个二进制位。假设q的类型是long int型(8字节,64个二进制位),那么q+1就是往后挪了64个二进制位。
达到你想法的做法(用书本上的东西),我想到的是通过位运算中是“按位与”和“右移”
即(没上机调试,可能有错,请看其思想):
int a=某个数,你想提取是数
int b[32]={0};
int t=1;这个t的二进制形式是0000 0000 0000 0001
int i=0;这个是移动的位数
for(i=0;i=32;i++)
b[32-i-1]=(ai)t;
思想是:假设a是0000 0000 0000 0101
那么
当i=0时,是0000 0000 0000 0101 0000 0000 0000 0001 = 0000 0000 0000 0001 = 整型的1
当i=1时,是(右移了一位以后的)0 0000 0000 0000 010 0000 0000 0000 0001 = 0000 0000 0000 0000 = 整型的0
当i=2时,是(右移了二位以后的)00 0000 0000 0000 01 0000 0000 0000 0001 = 0000 0000 0000 0001 = 整型的1
……以此类推,这样可以提取出来每个二进制,符合你的要求