C语言指针的内存分配和Java中的引用
2017-03-06 17:27
411 查看
核心内容:
1、C语言指针的核心知识点
2、处理指针相关问题的万能措施—-内存分配图
3、C语言的指针是如何过渡到Java中的引用的
最近一段时间一直在学习C语言的指针,也算是颇有心得吧,虽然从网上看了几篇关于指针的博文,但是感觉都不符合自己的口味,于是决定好好写一篇关于指针的文章。
C语言指针的核心知识点:
1、指针就是地址,地址就是内存单元的编号,范围是0到4G-1,指针的本质就是一个操作受限的非负整数,而指针变量就是存放内存单元编号(即地址、指针)的变量。
2、凡是动态分配的内存,都是没有名字的,而是将其地址赋给一个指针变量,用指针变量去代表这个事物。
3、一个指针变量,无论其指向的变量占多少个字节,其本身只占用4个字节的内存空间,因为内存单元的编号是32位。32/8=4
4、字节是存储数据的基本单元,一个字节占8位,而一个字节的编号占32位。
5、变量分为两种类型:普通类型变量和指针类型变量,其中普通类型变量用来存放真实的数据,而指针类型变量用来存放变量的地址。其中指针类型变量包括(Java中):
①所有类定义的变量:如 Student student = new Student(“zhang” , 25),其中的student
②所有接口定义的变量:如 List list = new ArrayList(),其中的list
③数组的名字:如int a[] = {1,2,3,8,9}中的a。
6、静态内存是在栈中进行分配的,是由系统自动分配、自动释放的,静态内存是程序员无法控制的;动态内存是在堆中进行分配的,是由程序员手动分配,手动释放的,凡是动态分配的内存必须通过free的方式才能够进行释放,当然这里指的是C语言;在Java当中,动态分配的内存是由内存回收机制来回收的,不用程序员来进行手动回收,保证了程序的安全性,但是在Java当中,由于虚拟机要一直跟踪每一块内存空间的使用情况,所以往往会从造成CPU的使用率过大。
好的,如果你想学会C语言中的指针,上面的这些内容是你必须要理解的,首先我们先理解一下究竟什么是指针,在理解究竟什么是指针之前,我们必须要知道数据在内存中究竟是如何来进行存储的,先放一张图:
这里通过一个小例子来说明数据在内存中是如何来进行存储的:
当我们在Visiual C++6.0软件对这个程序进行编译运行的时候,Visiual C++6.0这个软件首先请求操作系统为我们的变量i分配一块内存空间,随后操作系统会在内存中寻找一块空闲的区域分配给我们的程序,随后Visiual
C++6.0这个软件会将变量i和我们的这块内存空间关联起来,今后对变量i的操作就是对我们内存空间的操作。具体实现过程如下:
现在我们对内存存储的这一块区域进行放大:
操作系统会给我们的变量分配一块内存空间,但是这块内存空间究竟在内存中的什么位置呢?这块内存空间在内存空间中的编号到底是多少呢?现在让我么在程序中输出一下:
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
运行结果:
现在我们用图画在描述一下:
在上面这张图中:
(即编号1)就是我们所说的指针,即地址,也就是说:指针实际上就是内存单元的编号,一个编号为32位,每一个内存单元都会占有一个内部单元的编号(即地址)记载其在内存条中的位置,因此通过指针我们可以直接对硬件进行操作。
其实,程序归根结底就是对内存的操作,我们对一块内存空间进行操作总共含有两种方式:
①直接通过变量名的方式对这块内存空间进行操作。(直接访问)
②通过获取内存空间的地址对这块内存空间进行操作。(间接访问)
其中,第一种方式是我们经常使用的,但是第二种方式会让我们有一种直接接触到硬件的感觉,示例程序:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
运行结果:
具体效果:
归根接地就是一句话:无论是通过变量名i的直接访问,还是通过地址18FF44的间接访问,本质上都是对同一块内存空间的访问。
处理指针相关问题的万能措施—-内存分配图
很多人在处理指针这块的程序的时候,有的时候总是会感觉到很迷糊,但是就我个人而言,对于指针相关的知识,总是习惯于去画内存分配图去解决问题,而且效果还是非常好的,下面我们就用一个典型的程序:交换内容的程序来说明问题。
要求:输入a和b两个整数,按照先大后小的顺序输出a和b。
实例程序1:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
运行结果:
很明显,从运行结果上来看,并没有达到我们的预期效果,下面我们用内存分配图来查找一下原因:
所以上面程序的解法是错误的。
实例程序2:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
运行结果:
内存分配图:
通过上面的图解我们可以发现,指针变量p和q分别定位到了变量a和变量b的内存空间,间接的交换了a和b内存空间的内容。
C语言的指针是如何过渡到Java中的引用的
在谈到这个问题的时候,我认为应该从两个方面进行说起:动态内存分配和如何传递发送内容。
动态内存份分配的问题:
实例程序1:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
运行结果:
内存实例图示:
对于上面的这个程序,Java语言是这么封装的:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
下面我们通过函数传递数据:传递指针变量(本质传递的是地址)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
运行结果:
Java封装的效果:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
运行结果:
2
3
4
5
6
1
2
3
4
5
6
总结:在Java当中,虽然已经没有了指针,但是底层编译运行过程中本质上就是指针,Java中的引用本质上就是C语言中的指针变量,无论是C语言还是Java语言,都有一个共同的特点:凡是动态分配的内存都是没有名字的,而是用一个指针变量保存这块内存空间的地址,用这个指针变量去代表这块内存空间。
1、C语言指针的核心知识点
2、处理指针相关问题的万能措施—-内存分配图
3、C语言的指针是如何过渡到Java中的引用的
最近一段时间一直在学习C语言的指针,也算是颇有心得吧,虽然从网上看了几篇关于指针的博文,但是感觉都不符合自己的口味,于是决定好好写一篇关于指针的文章。
C语言指针的核心知识点:
1、指针就是地址,地址就是内存单元的编号,范围是0到4G-1,指针的本质就是一个操作受限的非负整数,而指针变量就是存放内存单元编号(即地址、指针)的变量。
2、凡是动态分配的内存,都是没有名字的,而是将其地址赋给一个指针变量,用指针变量去代表这个事物。
3、一个指针变量,无论其指向的变量占多少个字节,其本身只占用4个字节的内存空间,因为内存单元的编号是32位。32/8=4
4、字节是存储数据的基本单元,一个字节占8位,而一个字节的编号占32位。
5、变量分为两种类型:普通类型变量和指针类型变量,其中普通类型变量用来存放真实的数据,而指针类型变量用来存放变量的地址。其中指针类型变量包括(Java中):
①所有类定义的变量:如 Student student = new Student(“zhang” , 25),其中的student
②所有接口定义的变量:如 List list = new ArrayList(),其中的list
③数组的名字:如int a[] = {1,2,3,8,9}中的a。
6、静态内存是在栈中进行分配的,是由系统自动分配、自动释放的,静态内存是程序员无法控制的;动态内存是在堆中进行分配的,是由程序员手动分配,手动释放的,凡是动态分配的内存必须通过free的方式才能够进行释放,当然这里指的是C语言;在Java当中,动态分配的内存是由内存回收机制来回收的,不用程序员来进行手动回收,保证了程序的安全性,但是在Java当中,由于虚拟机要一直跟踪每一块内存空间的使用情况,所以往往会从造成CPU的使用率过大。
好的,如果你想学会C语言中的指针,上面的这些内容是你必须要理解的,首先我们先理解一下究竟什么是指针,在理解究竟什么是指针之前,我们必须要知道数据在内存中究竟是如何来进行存储的,先放一张图:
这里通过一个小例子来说明数据在内存中是如何来进行存储的:
当我们在Visiual C++6.0软件对这个程序进行编译运行的时候,Visiual C++6.0这个软件首先请求操作系统为我们的变量i分配一块内存空间,随后操作系统会在内存中寻找一块空闲的区域分配给我们的程序,随后Visiual
C++6.0这个软件会将变量i和我们的这块内存空间关联起来,今后对变量i的操作就是对我们内存空间的操作。具体实现过程如下:
现在我们对内存存储的这一块区域进行放大:
操作系统会给我们的变量分配一块内存空间,但是这块内存空间究竟在内存中的什么位置呢?这块内存空间在内存空间中的编号到底是多少呢?现在让我么在程序中输出一下:
# include <stdio.h> int main() { int i = 10; printf("编号1的数值是:%#X\n",&i); return 0; }1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
运行结果:
现在我们用图画在描述一下:
在上面这张图中:
(即编号1)就是我们所说的指针,即地址,也就是说:指针实际上就是内存单元的编号,一个编号为32位,每一个内存单元都会占有一个内部单元的编号(即地址)记载其在内存条中的位置,因此通过指针我们可以直接对硬件进行操作。
其实,程序归根结底就是对内存的操作,我们对一块内存空间进行操作总共含有两种方式:
①直接通过变量名的方式对这块内存空间进行操作。(直接访问)
②通过获取内存空间的地址对这块内存空间进行操作。(间接访问)
其中,第一种方式是我们经常使用的,但是第二种方式会让我们有一种直接接触到硬件的感觉,示例程序:
# include <stdio.h> int main() { int i = 10; printf("编号1的数值是:%#X\n",&i); int * p = &i; //指针变量p保存了变量i的地址:18FF44 *p = 100; //以18FF44为地址的那块内存空间的内容设置为100 printf("变量i的内容是:%d\n",i);//无论是直接访问还是以地址的间接访问,本质上都是对同一块内存空间的访问 return 0; }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
运行结果:
具体效果:
归根接地就是一句话:无论是通过变量名i的直接访问,还是通过地址18FF44的间接访问,本质上都是对同一块内存空间的访问。
处理指针相关问题的万能措施—-内存分配图
很多人在处理指针这块的程序的时候,有的时候总是会感觉到很迷糊,但是就我个人而言,对于指针相关的知识,总是习惯于去画内存分配图去解决问题,而且效果还是非常好的,下面我们就用一个典型的程序:交换内容的程序来说明问题。
要求:输入a和b两个整数,按照先大后小的顺序输出a和b。
实例程序1:
# include <stdio.h> void swap(int ,int ); int main() { int a,b; printf("请从键盘上输入a和b两个数值:\n"); scanf("%d %d",&a,&b); if (a < b) { swap(a,b); } printf("max=%d \t min=%d \n",a,b); return 0; } void swap(int p,int q) { int tmp; //交换p和q的内容 tmp = p; p = q; q = tmp; }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
运行结果:
很明显,从运行结果上来看,并没有达到我们的预期效果,下面我们用内存分配图来查找一下原因:
所以上面程序的解法是错误的。
实例程序2:
# include <stdio.h> void swap(int *,int *); int main() { int a,b; printf("请从键盘上输入a和b两个数值:\n"); scanf("%d %d",&a,&b); if (a < b) { swap(&a,&b); } printf("max=%d \t min=%d \n",a,b); return 0; } void swap(int *p,int *q) { int tmp; tmp = *p; *p = *q; *q = tmp; }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
运行结果:
内存分配图:
通过上面的图解我们可以发现,指针变量p和q分别定位到了变量a和变量b的内存空间,间接的交换了a和b内存空间的内容。
C语言的指针是如何过渡到Java中的引用的
在谈到这个问题的时候,我认为应该从两个方面进行说起:动态内存分配和如何传递发送内容。
动态内存份分配的问题:
实例程序1:
# include <stdio.h> # include <malloc.h> # include <string.h> struct Student { char name[100]; int age; float score; }; int main() { Student * student = (Student *)malloc(sizeof(Student)); strcpy(student->name,"zhangming"); student->age = 25; student->score = 88.8f; printf("name is %s\n",student->name); //student->age在编译底层会变为(*student).name printf("age is %d\n",student->age); printf("score is %f\n",student->score); return 0; }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
运行结果:
内存实例图示:
对于上面的这个程序,Java语言是这么封装的:
class Student { String name; int age; float score; } public class App1 { public static void main(String[] args) { //Student * student = (Student *)malloc(sizeof(Student)); Student student = new Student(); //new相当于C语言中的malloc student.name = "zhangsan"; student.age = 25; student.score = 88.8f; System.out.println("name is:"+student.name); System.out.println("age is:"+student.age); System.out.println("score is:"+student.score); } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
下面我们通过函数传递数据:传递指针变量(本质传递的是地址)
# include <stdio.h> # include <malloc.h> # include <string.h> struct Student { char name[100]; int age; float score; }; void changeData(Student * stu) { strcpy(stu->name,"lisi"); stu->age = 24; stu->score = 98.8f; } int main() { Student * student = (Student *)malloc(sizeof(Student)); strcpy(student->name,"zhangming"); student->age = 25; student->score = 88.8f; printf("name is %s\n",student->name); //student->age在编译底层会变为(*student).name printf("age is %d\n",student->age); printf("score is %f\n",student->score); changeData(student);//传递的是地址,速度快并且节省内存空间! printf("name is %s\n",student->name); //student->age在编译底层会变为(*student).name printf("age is %d\n",student->age); printf("score is %f\n",student->score); return 0; }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
运行结果:
Java封装的效果:
class Student { String name; int age; float score; } public class App1 { public static void main(String[] args) { //Student * student = (Student *)malloc(sizeof(Student)); Student student = new Student(); //new相当于C语言中的malloc student.name = "zhangsan"; student.age = 25; student.score = 88.8f; System.out.println("name is:"+student.name); System.out.println("age is:"+student.age); System.out.println("score is:"+student.score); changeData(student); //student本质上是一个指针变量 System.out.println("name is:"+student.name); System.out.println("age is:"+student.age); System.out.println("score is:"+student.score); } public static void changeData(Student stu) //stu指向同一块内存空间 { stu.name = "lisi"; stu.age = 24; stu.score = 98.8f; } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
运行结果:
name is:zhangsan age is:25 score is:88.8 name is:lisi age is:24 score is:98.81
2
3
4
5
6
1
2
3
4
5
6
总结:在Java当中,虽然已经没有了指针,但是底层编译运行过程中本质上就是指针,Java中的引用本质上就是C语言中的指针变量,无论是C语言还是Java语言,都有一个共同的特点:凡是动态分配的内存都是没有名字的,而是用一个指针变量保存这块内存空间的地址,用这个指针变量去代表这块内存空间。
相关文章推荐
- Java中堆内存和栈内存_在建立一个对象时从两个地方都分配内存,在堆中分配的内存实际建立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的指针(引用)。修改栈指针就可以把栈中的内容销毁.这样最快
- java的引用和C语言指针的探讨
- java的引用和C语言指针的探讨
- java 值传递跟引用传递在内存中怎么分配的
- Java垃圾收集器与内存分配策略、Java中四种引用类型
- java 值传递跟引用传递在内存中怎么分配的
- Java学习之旅基础知识篇:数组及引用类型内存分配
- C语言 内存分配 地址 指针 数组 参数 实例解析
- C语言结构体,C语言结构体指针,java对象引用,传值,传地址,传引用
- C语言 内存分配 地址 指针 数组 参数 实例解析
- Java垃圾收集器与内存分配策略、Java中四种引用类型
- C语言二维数组的分配(记录我的指针引用错误)
- 修改的 创建队列程序 C语言。 队列元素 是堆分配内存,而非指针
- C语言 内存分配 地址 指针 数组 参数 实例解析
- C语言——指针与结构体 内存的动态分配
- C语言学习9: malloc动态内存存储,动态内存分配去空格字符增长版,动态内存分配去符号incr增长版,型参和返回值都是int型的函数的指针,main函数的地址也可以用指针指向,typedef定义函数指针,函数定义与嵌套的作用,返回函数指针类型,const作用
- C语言 内存分配 地址 指针 数组 参数 实例解析
- 【嵌入式开发】C语言 内存分配 地址 指针 数组 参数 实例解析
- java static 静态代码块,在内存中只有一块,而且会记住指针的引用,
- C语言 内存分配 地址 指针 数组 参数 实例解析