一:变量的内存分配
一:不同数据类型的内存分配
引入:计算下列变量所占的内存字节大小
char c='a';
char b='c';
int i = 100;
int* p;
可能有很多种不一样的答案,但是标注的答案就是是1,1, 4。系统对变量内存空间的分配只取决于他的数据类型,与他本身的大小无关。一个int类型的数据就是占四个字节,一个char类型数据就是占一个字节,不可能改变的,还有我们最重要的指针变量,永远都是和他cpu的字节数有关(32位平台指针内存大小恒为4字节)
0 | 0 | 0 | char c |
哪怕他本身数据大小一个字节就可以搞定,但是只要他的数据类型是int他的占内存空间就百分百是四个字节,剩下的就算空着也不会让给其他人。通俗点来讲就是我的东西就算我占着也不可能给你们用。
二:单个char类型数据的内存分配
我们都知道在C语言中一个char型变量占有空间是一个字节,但是由于我们硬件的设计上,喜欢一次一次的调用四个字节,在默认分配上虽然char只占一个字节,但还是会给他分配四个字节的内存,只不过其他三个内存处于浪费状态。
int mian()
{
char i;//我的兄弟们
return 0;
}
浪费 | 浪费 | 浪费 | char |
当有一个新的char数据,就少浪费一个,有点类似于我们大学生占位置,我一个人可以占四个位置,但是我只能座一个位置,也就相当于对于其他人而言另外的三个位置是被浪费掉的,只有和我“类型”一样的兄弟们来了,被我浪费的三个位置才能少浪费一个。这样一个就可以很好的理解了。
浪费 | char | char | char |
(这里有没有怀念大学期间为你占位置的好兄弟啦)
三:内存冲突
什么叫内存冲突呢,这里我们先从冲突来讲,一般情况下怎么样会有冲突,那就是你抢了我的东西,在C语言里面,系统会默认给每一个数据分配内存,我们大家井水不犯河水,其乐融融。但是总有一些不收规矩的家伙,会抢占一些内存来,这个强盗在C语言里面就是指针,我们大家都知道指针有不同的指针类型,但是对他的作用肯定也是一知半解,下面我们通过这段代码来讲解内存冲突。
int main() { char c='a'; char b='c'; int i = 100; int* p; p = (int*)&c; *p = 123;
我们这里定义了两个char类型的变量,他们两个占有了一块四字节的内存,如下所示。他们浪费两块空间,在这里还一切正常。接下来我们定义了一个int的数据类型,并且给他分配了一块四字节的空间,在这里也是井水不犯河水。
浪费 浪费 char b char a
捣蛋鬼出来了,对就是他,我们定义了一个int *p;的指针,我们给指针p分配一块四字节的空间用来存放char c;的地址。这里这个捣蛋鬼似乎还挺遵守规则,接下来,*p=123,我们对指向char c的地址赋值,也就是给char c;赋值,但是这个时候因为*p是int类型的,他会默认占据四个字节的空间,给char a;的起始地址赋值,同时也就抢占了b的内存。抢占前:
浪费 浪费 char b char a 抢占后:这个时候char b的地址就被抢占了,也就是内存冲突。、
0 0 0 123
这个时候b的值就会默认赋值为0;
二:关于程序的执行
一:程序执行的大致流程
代码:
#include<stdio.h>
#include<sqlist.h>
int i,j;
int a;
int main()
{
char c='a';
char b='c';
int i = 100;
int* p;
p = (int*)&c;
*p = 123;
//指针,不管你是什么类型的指针,在内存中永远都是一样的。
a = 123;//在内存里面必然有一定空间,即在内存里写123
//1.CPU来写123 2.怎么知道写123,即通过指令。
return 0;
}
在这里我们要对变量a进行赋值,那么在计算机内部他是怎么执行的呢,
一般来说是分为下列操作
1.CPU从FLASH里面读取指令,然后CPU进行运算,进而对RAM内存进行操作。
这里关于指令:
也就是说想对这个变量进行操作,我们得先得到这个变量的地址,然后对这个地址的数据进行修改。(等等这是不是很熟悉,这个功能和C语言中的指针变量是不是特别相似)
也就是说从某种意义上来讲,这两端代码是等价的。
#include<stdio.h>
int i;
int main()
{
i=100;//对进行赋值
int*p;
p=&i; //读取i的地址
*p=100 //对读取的数据进行赋值
}
二:程序执行类比指针
#include<stdio.h>
int i;
int main()
{
i=100;//对进行赋值
int*p;
p=&i; //读取i的地址
*p=100 //对读取的数据进行赋值
}