这个原因是因为我们学C语言之初就没有从根本理解C语言程序在运行中的情况
现在一般的大学课程或C语言相关入门书籍上讲解指针一般都会用如下办法
首先告诉你指针是用来指向地址的,问号三连
然后告诉你声明指针的方法如下
int *i=(int *)malloc(sizeof(int)); 或者 int i=0; int *p=&i;
然后给你举一大堆例子,之后你感觉你好像明白指针怎么用了。
过了一段时间你越用越熟练,你感觉指针也就很一般没什么难的。
直到有一天你遇到了双重指针在传参中的应用,从此你抛弃了C使用了C++
之后你习惯了使用引用——'&'方法当参数,你每次遇到纯C的时候遇到双重指针都需要重新理解一番
我觉得准备用两篇文章彻底搞定你对变量和指针及动态分配内存的理解
栈是一个数据结构上的概念,对初步理解C语言程序机制毫无帮助,所以这里我就不叙述了
栈区的主要目的是存放局部变量
无论是main还是其他函数亦或for循环中声明的变量
全部是存放在栈区的
随着函数或代码段的运行结束,这些函数的内存空间就会被释放,这个过程是由编译器处理的。
堆区的主要作用是存放的是动态分配内存的内存块
比如C语言的malloc函数或C++的new 关键字 定义的内存块都是存放在堆中的
这样定义的内存块是不会自动销毁的,直到遇到free函数或delete 关键字释放
所以C/C++经常会遇到内存泄露的情况,有一些编程语言采用了GC机制解决了这个问题
静态区存放的是全局变量和静态变量,静态区的变量从程序到结束都一直存在不会被销毁
只读区用来存放指令序列(代码段)和常量
我们可以测试一下int、void和自定义结构体指针的大小
printf("size of int * is:%d\n",sizeof(int *));
printf("size of void * is:%d\n",sizeof(void *));
printf("size of struct Test * is:%d\n",sizeof(struct Test *));
我们发现所有的指针型变量都是八个字节,这和我的64位编译器有关,如果是32位的就应该是四个字节
当我们创建一个指针型变量的时候其实就是在栈中创建了一个普通变量,这个变量的值是一个地址
我们注意到同样一个事物在不同的地方,它的意义就不同,编程语言也是一样
在指针型变量的声明和定义过程中,*只是语法的一部分
但在我们使用指针型变量时,*是一个单目操作符
int *a=(int *)malloc(sizeof(int *); //定义一个指针型数据并开辟一块动态内存
*a=100; //如下图所示
开篇我们针对C语言程序在实现层的一些介绍,终篇我们将针对指针部分进行讨论
我们仍然要注意以下几点
1、如果我们没有使用动态分配内存,比如我们让指针指向一个变量i,那么指针指向的内存区域也将是栈中的地址,这时是不能对这个指针执行free操作的,会在执行中出错。
2、指针类型的作用是判断指针指向数据的长度,即从首地址开始读取多少数据,此处细节处理本篇不予讨论
3、使用free()函数释放的内存,仅仅是解除对内存区域的占用,内存中的数据在未被替换前依旧存在(被释放的内存区域为自由区域,会随着程序正常的执行被替换属于非法数据)