浅谈C,C++语言的基本数据类型的内存分配和指针的内存分配
2017-03-24 17:47
381 查看
C语言的基本类型变量的内存分配和指针内存分配方式的对比(int类型)
变量内存分配:
代码如下:
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
结果分析:
我们知道,一个变量要想在计算机中进行存储,则必须有一个内存地址和内存空间,内存地址就像一把钥匙,内存空间就像一所房间,房间里面可以存放货物,但是你想拿到 货物必须先打开房间的锁头,才能进去房间里面那货物。如图:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/20/854b80492227d2d70e6c4a0f4ed743af)
定义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)
指针内存分配:
代码如下:
运行结果:
手动为指针变量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
结果分析:
指针变量的引用做为函数形参时,该形参会获取函数实参的地址和内容(即值);
指针变量做为函数形参时,该形参会获取函数实参的内容,并不会获取实参的地址,在编译时,系统会自动为该形参分配一个地址
指针变量和“指针变量的引用”(其类型和指针变量的类型一致):
为了更加清楚的比较“指针变量”和“指针变量的引用”的区别,特此编写了下面这两段代码
代码一:
运行结果:
执行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
代码二:
运行结果:
执行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
图解:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/20/8619c52697139e10a1198f8274a10c58)
如果你是一名C语言初学者,并且详细看了本博文,至于对该程序的结果分析,相信也一目了然了。如有困惑的地方,请留言。
变量内存分配:
代码如下:
#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语言初学者,并且详细看了本博文,至于对该程序的结果分析,相信也一目了然了。如有困惑的地方,请留言。
相关文章推荐
- 学点 C 语言(23): 数据类型 - 给指针分配内存
- C语言学习7 :二级指针定义,强制转换,多级指针初步,6级指针构造,错误应用*p=&a,错误应用 二级p2,void型指针的兼容性,malloc函数基本用法,malloc分配空间和堆栈空间的区别,验证malloc函数内存的分配,验证malloc函数的越界,内存泄漏,指针不能返回局部变量地址,内存分配
- String对象内存分配和基本数据类型的默认值与初始化相关问题
- java基本数据类型内存分配
- Java基本数据类型的内存分配
- 浅谈js基础数据类型和引用类型,深浅拷贝问题,以及内存分配问题
- 类是数据类型,对象是内存的具体分配
- 类是数据类型,对象是内存的具体分配
- 《coredump问题原理探究》Linux x86版5.2节C风格数据结构内存布局之基本数据类型
- 关于内存和指针操作,数据类型转换本质的理解
- 指针(内存大小和数据类型无关,和系统操作位数有关),对象,地址,和系统操作位数的关系
- 关于内存和指针操作,数据类型转换本质的理解
- 浅谈Java API中基本数据类型包装类的缓存设计
- 指针部分释疑之二:内存的分配及内存错误类型
- 基本数据类型的表现形式(地址,指针,引用)
- 基本数据类型之二:指针
- 浅谈C#基本数字数据类型
- 关于内存和指针操作,数据类型转换本质的理解
- JAVA基本数据类型占用内存大小
- Linux设备驱动程序学习之数据类型与内存分配 .