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

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


  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值