您的位置:首页 > 编程语言 > C语言/C++

浅谈C,C++语言的基本数据类型的内存分配和指针的内存分配

2017-03-24 17:47 381 查看
C语言的基本类型变量的内存分配和指针内存分配方式的对比(int类型)

变量内存分配:

代码如下:

#include"stdio.h"
#include"stdlib.h"

void main(){
int i  ;
int j = 0 ;
int k = NULL ;
int L = 10;
int M = 11 ;
printf("i的内存地址(&i)=%d,i的值为(i)=%d\n",&i,i);
printf("j的内存地址(&j)=%d,j的值为(j)=%d\n",&j,j);
printf("k的内存地址(&k)=%d,k的值为(k)=%d\n",&k,k);
printf("L的内存地址(&L)=%d,L的值为(L)=%d\n",&L,L);
printf("M的内存地址(&M)=%d,M的值为(M)=%d\n",&M,M);

M = 3 ;
printf("M的内存地址(&j)=%d,M的值为(L)=%d\n",&M,M);
L=2;
L=(int)malloc(sizeof(int));
printf("L的内存地址(&j)=%d,L的值为(L)=%d\n",&L,L);
}
运行结果如下:

i的内存地址(&i)=1703740,i的值为(i)=-858993460

j的内存地址(&j)=1703736,j的值为(j)=0

k的内存地址(&k)=1703732,k的值为(k)=0

L的内存地址(&L)=1703728,L的值为(L)=10

M的内存地址(&M)=1703724,M的值为(M)=11




M的内存地址(&j)=1703724,M的值为(L)=3

L的内存地址(&j)=1703728,L的值为(L)=34109368


结果分析:

我们知道,一个变量要想在计算机中进行存储,则必须有一个内存地址和内存空间,内存地址就像一把钥匙,内存空间就像一所房间,房间里面可以存放货物,但是你想拿到 货物必须先打开房间的锁头,才能进去房间里面那货物。如图:



定义5个整形变量:

整形变量“i”:手动给i 赋值并未分配内存空间,但是却输出了变量i的地址和值(一个未知的值)。

整形变量“j”:手动给i 赋值(j=0)并未分配内存空间,输出了变量i的地址和值(0)。

整形变量“k”:手动给k 赋值(k=NULL)并未分配内存空间,输出了变量i的地址和值(0)。

整形变量“L”:手动给i 赋值(L=10)并未分配内存空间,输出了变量i的地址和值(10)。

整形变量“M”:手动给i 赋值(M=11)并未分配内存空间,输出了变量i的地址和值(10)。

由此可知道,在C语言中,声明一个变量,如果该变量未赋值的话,系统会自动把一个未知的数赋值给此变量,在编译程序时,为该变量分配内存。(同时可发现在C语言里,(int) NULL = 0)

指针内存分配:

代码如下:

#include"stdio.h"
#include"stdlib.h"
//a:指针变量的引用
void test_1(int * & a){
printf("执行test_1()Method中形参a的地址=%d,a的值=%d\n\n",&a,a);
}
void test_2(int * a){
printf("执行test_2()Method中形参a的地址=%d,a的值=%d\n\n",&a,a);
}
void main(){
int * a ;  //a:指向整形数据的指针变量
printf("手动为指针变量a赋值前:\n");
printf("执行test_1()Method之前的a的地址=%d,a的值=%d\n",&a,a);
printf("开始执行test_1(int * & a) Method\n");
test_1(a);
printf("开始执行test_2() Method\n");
test_2(a);

printf("\n");
printf("手动为指针变量a赋值后:\n");
int i = 10 ;
a=&i;
printf("执行test_1()Method之前的a的地址=%d,a的值=%d\n",&a,a);
printf("开始执行test_1(int * & a) Method\n");
test_1(a);
printf("开始执行test_2() Method\n");
test_2(a);

}


运行结果:
手动为指针变量a赋值前:

执行test_1()Method之前的a的地址=1703740,a的值=-858993460

开始执行test_1(int * & a) Method

执行test_1()Method中形参a的地址=1703740,a的值=-858993460

开始执行test_2() Method

执行test_2()Method中形参a的地址=1703656,a的值=-858993460

手动为指针变量a赋值后:

执行test_1()Method之前的a的地址=1703740,a的值=1703736

开始执行test_1(int * & a) Method

执行test_1()Method中形参a的地址=1703740,a的值=1703736

开始执行test_2() Method

执行test_2()Method中形参a的地址=1703656,a的值=1703736

结果分析:

指针变量的引用做为函数形参时,该形参会获取函数实参的地址和内容(即值);

指针变量做为函数形参时,该形参会获取函数实参的内容,并不会获取实参的地址,在编译时,系统会自动为该形参分配一个地址

指针变量和“指针变量的引用”(其类型和指针变量的类型一致):

为了更加清楚的比较“指针变量”和“指针变量的引用”的区别,特此编写了下面这两段代码

代码一:

#include"stdio.h"
#include"stdlib.h"
int j = 10 ;
//a:指针变量的引用
void test_1(int * & a){
a=&j;
printf("test_1()方法*a=%d\n",*a);
printf("执行test_1()Method中形参a的地址=%d,a的值=%d\n\n",&a,a);
}
void test_2(int * a){
printf("test_2()方法*a=%d\n",*a);
printf("执行test_2()Method中形参a的地址=%d,a的值=%d\n\n",&a,a);
}
void main(){
int * a ;  //a:指向整形数据的指针变量
printf("手动为指针变量a赋值前:\n");
printf("执行test_1()Method之前的a的地址=%d,a的值=%d\n",&a,a);
printf("开始执行test_1(int * & a) Method\n");
test_1(a);
printf("开始执行test_2() Method\n");
test_2(a);

printf("main方法*a=%d\n",*a);
}


运行结果:

执行test_1()Method之前的a的地址=1703740,a的值=-858993460

开始执行test_1(int * & a) Method

test_1()方法*a=10

执行test_1()Method中形参a的地址=1703740,a的值=4345228

开始执行test_2() Method

test_2()方法*a=10

执行test_2()Method中形参a的地址=1703660,a的值=4345228

main方法*a=10


代码二:

#include"stdio.h"
#include"stdlib.h"
int j = 10 ;
//a:指针变量的引用
void test_1(int * & a){
printf("执行test_1()Method中形参a的地址=%d,a的值=%d\n\n",&a,a);
}
void test_2(int * a){
a=&j;
printf("test_2()方法*a=%d\n",*a);
printf("执行test_2()Method中形参a的地址=%d,a的值=%d\n\n",&a,a);
}
void main(){
int * a ;  //a:指向整形数据的指针变量
printf("执行test_1()Method之前的a的地址=%d,a的值=%d\n",&a,a);
printf("开始执行test_1(int * & a) Method\n");
test_1(a);
printf("开始执行test_2() Method\n");
test_2(a);

printf("main方法*a=%d\n",*a);
}


运行结果:

执行test_1()Method之前的a的地址=1703740,a的值=-858993460

开始执行test_1(int * & a) Method

执行test_1()Method中形参a的地址=1703740,a的值=-858993460

开始执行test_2() Method

test_2()方法*a=10

执行test_2()Method中形参a的地址=1703660,a的值=4345228


 代码打印到这就发生了崩溃,原因是执行了这一句"printf("main方法*a=%d\n",*a);" , 那为啥会发送崩溃呢?究其原因是 " *a "惹的祸。

原因分析:

上面提到“指针变量的引用”和“指针变量”的区别,大家可能看的有点蒙?经过上述的两段代码想大家证明了

1:指针变量的引用(形参):函数形参和函数实参的共享同一块内存区,共享同一个地址,所以我对形参的改变就是对实参的改变

2:指针变量(形参):函数形参和函数实参不共享同一块内存区,不共享同一个地址,因为形参在编译时重新分配了内存和地址,内存里面存放的就是实参转过来的值。因为         此时的形参和实参都拥有不同的内存区和地址,所以形参的改变并不能影响实参的变化。

虽然我们在代码二里面的test_2(int * a)方法里面吧 "j"的地址父给了a,使指针变量a指向了j的内存区(*a=10),但是请注意,在test_2(int * a)方法里面的a是一个“指针变量”,并不是一个“指针变量的引用”,所以形参a改变不了实参a的值。

指针的指针:

既然我们说到了“指针变量”,“指针变量的引用(个人感觉也可以理解成:指针变量的别名)”,那我们也应该了解一下“指针的指针”,即“指针变量的指针变量”。

代码如下:

#include"stdio.h"
#include"stdlib.h"
int i = 10 ;
//a:指针的指针(指针变量指向的指针变量)
void test_1(int * * a){
printf("test_1(int * * a)方法中a的值=%d,a的地址%d,a指向的指针变量值=%d,j指向的指针变量所指向的值=%d\n",a,&a,*a,**a);
}
void test_2(int * a){

printf("test_2(int * a)方法中a的值=%d,a的地址%d,a指向的值=%d\n",a,&a,*a);
}
void main(){
int * * j ; //指针的指针(指向指针变量的指针变量)
int * k ; //指针变量(存储地址)
printf("i的值=%d,i的地址%d\n",i,&i);
printf("为k赋值之前:\n");
printf("k的值=%d,k的地址%d\n",k,&k);

k=&i; //把i的地址赋值给指针变量k,使k得值等于i的地址

printf("为k赋值之后:\n");
printf("k的值=%d,k的地址%d,k指向的值=%d\n",k,&k,*k);
printf("为j赋值:\n");
j=&k; //把k的地址赋值给指向指针变量的指针变量j,使j得值等于k的地址
printf("j的值=%d,j的地址%d,j指向的指针变量值=%d,j指向的指针变量(k)所指向的值=%d\n",j,&j,*j,**j);
test_1(j);
test_2(k);
}

运行结果:
i的值=10,i的地址4345228

为k赋值之前:

k的值=-858993460,k的地址1703736

为k赋值之后:

k的值=4345228,k的地址1703736,k指向的值=10

为j赋值:

j的值=1703736,j的地址1703740,j指向的指针变量值=4345228,j指向的指针变量(k)所指向的值=10

test_1(int * * a)方法中a的值=1703736,a的地址1703656,a指向的指针变量值=4345228,j指向的指针变量所指向的值=10

test_2(int * a)方法中a的值=4345228,a的地址1703656,a指向的值=10


图解:






如果你是一名C语言初学者,并且详细看了本博文,至于对该程序的结果分析,相信也一目了然了。如有困惑的地方,请留言。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐