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

来源:互联网 发布:星际皆知你爱我微盘 编辑:程序博客网 时间:2024/06/05 07:03

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语言初学者,并且详细看了本博文,至于对该程序的结果分析,相信也一目了然了。如有困惑的地方,请留言。


0 0
原创粉丝点击