1、应用程序面对的地址实际是虚拟地址空间,每一个进程分配了一个独立的虚拟地址。
printf输出地址值输出的并不是真实的物理地址。
#include <stdio.h> int main() { int hoge; char buf[256]; printf("&hoge...%p\n",&hoge); printf("input initial value."); /*由于scanf连续从流中读入字符(换行也是一个字符),而不是以单位内容进行解释。 当输入"123\n"时候,scanf读取"123",而后面的getchar读取"\n" 而fgets和sscanf组合使用可以避免这个问题 */ fgets(buf,sizeof(buf),stdin); sscanf(buf,"%d",&hoge); for(;;) { printf("hoge...%d",hoge); getchar(); //等待回车 hoge++; } return 0; }
让程序在两个窗口运行,发现打印的hoge地址相同,但是,他们数据并没有发生任何影响。
2、
C语言的变量有区间性的作用域。这种作用域有三种:全局变量(在函数之外声明的变量,在任何地方可见,用extern连接)、文件内部的静态变量(在函数之外声明的static变量,只在本文件中有效)、局部变量(函数内声明的变量)。
C语言的变量还有存储期的差别。静态存储期(全局变量、文件内部的静态变量、局部static变量的寿命从程序开始运行到结束都一直存在)、自动存储期(非static局部变量,用“栈“的机制来实现)。还有动态分配内存malloc,直到free为止。
现在输出各类指针的地址:
#include <stdio.h> #include <stdlib.h> int global_var; static int file_static_var; void fun1() { int f1_var; static int f1_static_var; printf("&f1_var...%p\n",&f1_var); printf("&f1_static_var...%p\n",&f1_static_var); } void fun2() { int f2_var; static int f2_static_var; printf("&f2_var...%p\n",&f2_var); printf("&f2_static_var...%p\n",&f2_static_var); } int main() { printf("fun1...%p\n",fun1); //指向函数的指针 printf("fun2...%p\n",fun2); printf("string...%p\n","abc"); //指向字符串常量的指针 printf("&global_var...%p\n",&global_var); //指向字符串常量的指针 printf("&file_static_var...%p\n",&file_static_var); //指向字符串常量的指针 fun1(); fun2(); int *p=(int *)malloc(sizeof(int)); printf("&p...%p\n",p); //指向字符串常量的指针 free(p); return 0; }
测试可以知道:
静态变量(全局变量、文件内static变量、函数内static变量)的地址很近。
函数指针、字符串常量的地址相对较近。
而自动变量f1_var和f2_var的地址一样,且离其他变量很远。
函数指针一般用于:1、GUI作为监听时候调用;2、用函数指针数组对行为进行分类处理。
函数自身的指针和字符串分配到“只读内存区域”。由于函数本身不可能修改、字符串常量不允许修改,所以它们放在只读内存区域。
静态变量从程序启动一直在内存中,也就是它们占有固定的区域。
自动变量存储在栈中,一旦函数结束运行,相应的自动变量的内存区域就会释放。
函数调用的过程如下:
- 1、调用函数时,参数从后往前按顺序压栈。
- 2、与函数相关的返回信息返回地址压栈。
- 3、跳到被调用函数的地址。
- 4、函数的自动变量压栈。
- 5、计算,可能有时候会有值放到栈中。
- 6、函数结束后,自动变量内存释放,使用返回信息返回原来的地址。
- 7、栈中移除调用方的参数。
malloc分配指定尺寸大小的内存块,返回内存块的首地址,如果分配失败(内存不足),返回NULL。这块内存需要用free来释放。像这种可以用任意顺序来释放的内存区域称为“堆”。
free需要注意的问题:调用free之后是不能引用对应的内存区域;但是,这块区域并不会马上被破坏掉。例如下面中pa释放掉了 ,但是pb还在用他。
int *pa; pa=(int *)malloc(sizeof(int)); *pa=1234; int *pb=pa; free(pa); pa=NULL; printf("%d",*pb);
在大型程序中,可以做一个函数给free披一张皮,并且程序猿只能调用这个函数,在释放区域之前故意将区域破坏(可以胡乱的用一个像0xcc这样的值填充)。
3、大小端
小端模式:数据低位位于低字节中,数据高位位于高字节中;数据地址是低字节地址。
int a=0x12345678; unsigned char *pa=(unsigned char *)&a; printf("%x %p\n",pa[0],&pa[0]); //16进制整数输出第一个字节的值 printf("%x %p\n",pa[1],&pa[1]); //16进制整数输出第一个字节的值 printf("%x %p\n",pa[2],&pa[2]); //16进制整数输出第一个字节的值 printf("%x %p\n",pa[3],&pa[3]); //16进制整数输出第一个字节的值
测试结果为:
78 0012FF60
56 0012FF61
34 0012FF62
12 0012FF63
小端模式的数据存储如下:
4、字节对齐
相关推荐
文档包括堆和栈 内存管理 内存调试 内存使用规则
水滴石穿C语言之内存使用.pdf水滴石穿C语言之内存使用.pdf
linux c程序获取cpu使用率及内存使用情况
4. C语言内存对齐,提高寻址效率 5. 内存分页机制,完成虚拟地址的映射 6. 分页机制究竟是如何实现的? 7. MMU部件以及对内存权限的控制 8. Linux下C语言程序的内存布局(内存模型) 9. Windows下C语言程序的内存...
linux下C语言编程4-使用共享内存实现进程间通信
通过C语言,基本实现了内存管理过程中的创建、修改、删除等操作
比较详细的C语言内存管理讲解
C语言中级教程-6 内存使用
1-1 C语言内存管理方式 1-2 C语言内存管理 1-3 C语言内存使用要点及常见错误 1-4 在Windows下如何跟踪内存泄露 1-5 Windows内存管理简述 1-6 总结和建议读者的练习
Linux共享内存C语言编程示例(包含一个应用的范例)
接触过编程的人都知道,高级语言都能通过变量名来访问内存中的数据。那么这些变量在内存中是如何存放的呢?程序又是如何使用这些变量的呢?
C语言中级-6内存使用 C语言中级-6内存使用
linux下C语言编程4-使用共享内存实现进程间通信.pdf
C语言中级培训教程—内存使用 C语言中级培训教程—内存使用
推荐4款linux下的检测c语言编写的程序的内存泄漏工具 C语言和其他语言相比最大的特色就是能够操作内存 但是最常犯的错误也是内存泄漏(管杀不管埋) 所以我们需要用一些工具来帮助我们检测是否存在内存泄漏,存在多少 ...
1、C中内存分为四个区 栈:用来存放函数的形参和函数内的局部变量。由编译器分配空间,在函数执行完后由编译器自动释放。 堆:用来存放由动态分配函数(如malloc)分配的空间。是由程序员自己手动分配的,并且必须...
在C语言中,我们可以使用malloc、calloc和realloc等函数来动态分配内存空间。这些函数返回一个指向分配内存空间起始位置的指针,我们可以通过这个指针来访问和操作这块内存空间。同时,我们还可以使用free函数来释放...
C语言内存与指针的综合使用,配合C语言进行综合讲解指针内存
C 共享内存 2个程序之间传输数据。 内部有2个C文件,x1.c是共享内存的读取程序,x2.c是共享内存的写入程序
本篇主要讲述了嵌入式系统C 编程中内存操作的相关技巧.掌握并深入理解关于数据指针、函数指针、动态申请内存、const 及volatile ...我们之所以在嵌入式系统中使用C 语言进行程序设计,99%是因为其强大的内存操作能力!