以下内容很多c语言书中都有讲到,我只总结下,我所遇到的一些问题
我们先讲变量,
一个变量由三部分组成,变量名,变量的地址和地址所指的空间。
一般变量的存储有存在栈空间里和堆空间。这三部分存在映射关系(不然怎么使用),
据浅显了解,变量名或者说代码是存储在内存当中,由PCB调用(操作系统里的内容,没有深入研究,有疑问可以共同探讨),变量地址由cpu分配地址线(这个好像是组成原理的内容?),分配的空间自然就是内存了。这次简要谈及位于栈区和堆区的变量。下面附上各种变量存储的位置与生命周期、
存在于栈区的变量:
一般数据类型:
1)常用数据类型声明的变量,还有结构体类型,枚举类型等等。
int a,double b,char c,
struct node{
int a;char b;double c
}num[1010];
这些变量在声明的时候就已经分配了地址和内存空间,并在自己的作用域使用完后自动销毁。(关于作用域的知识,网友们自行百度哈)。因为是声明的时候就分配好固定的空间。所以我们定义数组的时候就只能定义固定长度的数组,如int num[100],char[1024]等。
2)常用变量的初始化:
1>什么是初始化
我们先来看什么是初始化,以下是来自百度百科的解释:
初始化
初始化就是把变量赋为默认值,把控件设为默认状态,把没准备的准备好。 但是如果是整个系统初始化那就不一样了。在汇编语言中,为变量分配空间时,初始化过的变量的初值位于可执行文件代码段数据后,会占用一定空间,不必要的初始化会造成磁盘空间的浪费。在C语言等高级语言中,为每一个变量赋初值被视为良好的编程习惯,有助于减少出现Bug的可能性。因此,是否对不必要的变量初始化依情况而定。
那么,假如你没有你真的没有给你声明的变量初始化呢,会出现什么情况?
我搜索了其他博客,认为这个观点最合理:
全局,静态变量,一般默认为0;
局部变量在栈上,取决于此处原来的数据,如果不初始化的话!
上面也很好理解,尽管没有初始化,我们声明的变量也是有初值的,不过是未知的值。所以对于应用高级语言的我们 。我们定义所有变量都要初始化,这是非常重要的一点,有很多同学有疑问,说我平常写的代码,一般都没初始化,也没发生什么事情啊。
2>我们不自觉地初始化
其实很多时候,你不自觉地已经把你定义的变量初始化了,因为相对于指针的来说的其他变量,是对于地址所对应空间上的数据进行操作的。所以初始化也比较简单。可以由用户输入,或者用常数对其赋值,你可能经常像下面这样写,
int a;
scanf("%d",&a);
又或者
int sum;
sum=8+7;
这些你可能不认为他是初始化,只是在后面使用了而已,可能你认为的初始化是下面这样(至少我曾经是这样认为的)
int a=8;
认为只有在声明的时候初始化,才叫初始化,其实给你声明的变量赋上初值就是所谓的初始化。对于自己声明的变量没有初始化是一种非常sha bi的行为。
指针类型:
1)指针的声明
回想一下我们定义指针的时候怎么定义的。我们先看简单数据类型声明的指针,
int *p, double *p.....
我们先理解一下各部分组成,int指的是这个指针所指的数据类型,p是指针指向的地址,,*p就是这个地址所指空间上的值。那么第一个问题。
2)指针的初始化
我们再来看百度百科对于指针初始化的定义:
指针初始化
指针初始化指的是对指针的重置。
我们刚讲对于一般变量的初始化的方法,一般变量是对于空间上的值进行操作的,而指针是通过地址来对空间进行操作的,所以我们对指针的初始化应该用地址去初始化。(也就是说用地址去重置已经声明的指针)所以对于指针的初始化也就比较简单了,我们常用取地址符‘ & ',来获取变量的地址。(这段话也告诉我们一个点,就是即使没有对指针初始化,他也是有地址,有内存空间的,但是未知,也是我们俗称的野指针)
int a=9;
int *p=&a;
或者,用数组名也行
int a[1010]={0};
int *p=a;
坚决不能这样
int *p=5;
有的编译器可能不会报错,但是不会运行出结果。更多初始化的方法,可以自己去查看更多的书籍,这里不再赘述。
存在于堆区的变量:
内存分区表中也显示的很清楚了,通过new/malloc申请的空间存,这一类变量也称之为动态变量,因为可以动态分配存储空间嘛。
我们这里也是讲它的初始化。
int *p;
p=(int*)malloc(100*sizeof(int));
大多数初学者可能会觉得这就是对指针的初始化,当然我看其他博客很多也讲在这里不用再去初始化也可以,但也有因为没有初始化翻车的情况所以还是强烈建议大家在这里也要初始化。毕竟不初始化是一种很shabi的行为。注意奥,malloc前面的(int*)一定要加上,因为malloc返回的是void*类型的指针,需要强制转换。
这里介绍一种比较常见的初始化方法(紧接上面代码):
memset(p,0,100*sizeof(int));
但是注意,这里的初始化与上面的用地址来初始化指针一样嘛!??
我们通过事例来观测一下,
1>先是用地址初始化指针:
int *p;
printf("未初始化 地址:%p 值:\n",p);
int q=9;
p=&q;
printf("初始化后 地址:%p 值:%d\n",p,*p);
return 0;
测试结果:
注:没有在未初始化输出值的原因是,未初始化的指针不能输出值,运行时会出错
由此我们,看见用地址初始化指针,地址发生了改变,指针所指空间的值也随地址改变而改变。
2>用memset初始化指针
int *p;
printf("未malloc: %p\n",p);
p=(int*)malloc(100*sizeof(int));
printf("malloc后: %p 值: %d\n",p,*p);
memset(p,0,100*sizeof(int));
printf("memset后: %p 值: %d\n",p,*p);
return 0;
结果:
由此可见malloc为指针赋上了新的地址,并且此空间上有值。类似我们用地址去初始化指针,
但是这个空间上的值,我们是不确定的,所以我们用memset对其空间上的值进行初始化,这一步就类似于我们对普通变量的初始化。