C语言指针传递和内存分配
来源:互联网 发布:linux matlab库 编辑:程序博客网 时间:2024/05/21 13:02
1.内存分配方式有三种:
(1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。
(2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。这里和Java有很大区别,Java函数调用的内部的存储单元都是在堆上创建的,所以Java需要虚拟机进行GC。
(在函数中不要返回栈内存,但可以返回动态分配的内存)。
(3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc 或new 申请任意多少的内存,程序员自己负责在何时用free 或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。
2.数据类型的本质:
C中没有 byte[] ,所以用usign char*(8bit) 代表 ,其实计算机中并没有char 类型,更准确的说计算机并没有数据类型,数据类型都是编译器定义的,比如 'd'的ascii是100(十六机制的0x64)
内存中存储的0x64(0110 0100),如果你认为它是int,那么它就是100(十进制) ;如果你认为它是char,那么它就是d;如果你认为它是字节,它就是unsign char
3.C的内存模型,指针变量名的本质就是内存地址,以下图为例,区分a+1 和 *a+1,a+1代表的是1002这个内存单元的内容,*a+1存储的是b
(2)在调用函数之前不知道字符串的长度
正确方法二:
需要注意的是返回值只能是动态分配的内存,如果是函数内的局部变量千万不要通过函数返回值,虽然可以返回,但是由于是在栈上分配的,所以可能会被下面的调用覆盖。
(1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。
(2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。这里和Java有很大区别,Java函数调用的内部的存储单元都是在堆上创建的,所以Java需要虚拟机进行GC。
(在函数中不要返回栈内存,但可以返回动态分配的内存)。
(3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc 或new 申请任意多少的内存,程序员自己负责在何时用free 或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。
2.数据类型的本质:
C中没有 byte[] ,所以用usign char*(8bit) 代表 ,其实计算机中并没有char 类型,更准确的说计算机并没有数据类型,数据类型都是编译器定义的,比如 'd'的ascii是100(十六机制的0x64)
内存中存储的0x64(0110 0100),如果你认为它是int,那么它就是100(十进制) ;如果你认为它是char,那么它就是d;如果你认为它是字节,它就是unsign char
3.C的内存模型,指针变量名的本质就是内存地址,以下图为例,区分a+1 和 *a+1,a+1代表的是1002这个内存单元的内容,*a+1存储的是b
4.区分可打印字符串和不可打印字符串:
char[3] a = {'x','y','z'}; //字符数组
char* a = "xyz";//末尾自动补零,它是可打印字符串
unsigned char* deviceID = "AA\0AAA";
printf("%d",strlen(deviceID)); //输出结果为2,但是真实长度是5,被截断了,是不可打印字符串,如果函数要返回deviceID给调用者,需要把deviceID的真实长度返回。
像Base64编码就是可打印的编码,即编码的结果没有'\0',不会被截断的。ASCII 字符是不可打印的。
5、函数返回指针的几种方法(以字符指针为例char *,特别注意返回不可打印的字符指针的问题)
typedef unsigned char byte;void print_char_string(byte *mychar, int len){ int i=0;for(i=0;i<len;i++){printf("%c->0x%x;",mychar[i],mychar[i]);}printf("\n");}
(1) 在调用函数之前可以获知字符串的长度
void test(byte *mychar){mychar[0] = 'a';mychar[1] = 'b'; mychar[2] = '\0';mychar[3] = 'd';mychar[4] = 'e';}int main(){ byte b[5]={0}; print_char_string(b,5); test(b); print_char_string(b,5); return (0);}
(2)在调用函数之前不知道字符串的长度
错误一:C函数调用是在栈上分配的,所以在函数内部定义的局部变量会随着函数调用的结束而出栈销毁,b不会被赋值。即使通过malloc分配内存也是不行的,b一直是NULL
void test(byte *mychar){mychar[0] = 'a';mychar[1] = 'b'; mychar[2] = '\0';mychar[3] = 'd';mychar[4] = 'e';}int main(){ byte *b = NULL; test(b); return (0);}
错误二:下面的方法把指针的地址作为参数调用函数,在函数内malloc,用完了由调用者free,但是忽略了字符的返回可能被截断的问题。
void test2(byte *p){p[0] = 'a';p[1] = 'b'; p[2] = '\0';p[3] = 'd';p[4] = 'e';}void test(byte **mychar){*mychar = (byte *)malloc(sizeof(byte) * 5); memset((void*)(*mychar), 0, 5);byte* p = *mychar;test2(p);}int main(){ byte *b = NULL; test(&b); print_char_string(b,strlen(b));//a->0x61;b->0x62;,因为b字符串包含了不可打印字符,造成了截断 free(b); return (0);}
正确方法一:
void test2(byte *p){p[0] = 'a';p[1] = 'b'; p[2] = '\0';p[3] = 'd';p[4] = 'e';}int test(byte **mychar){*mychar = (byte *)malloc(sizeof(byte) * 5); memset((void*)(*mychar), 0, 5);byte* p = *mychar;test2(p);return 5;}int main(){ byte *b = NULL; int length = test(&b); print_char_string(b,length); free(b); return (0);}
正确方法二:
通过函数返回值来传递动态内存,但是这个方法不能解决返回的字符串包含不可打印字符的问题,
byte* test3(){ byte *p = (byte *)malloc(sizeof(byte) * 5); memset((void*)(p), 0, sizeof(byte) * 5);p[0] = 'a';p[1] = 'b'; p[2] = '\0';p[3] = 'd';p[4] = 'e';return p;}int main(){ byte *b = test3(); free(b); return (0);}
需要注意的是返回值只能是动态分配的内存,如果是函数内的局部变量千万不要通过函数返回值,虽然可以返回,但是由于是在栈上分配的,所以可能会被下面的调用覆盖。
0 0
- C语言指针传递和内存分配
- C语言指针传递和内存分配
- C语言指针传递和内存分配
- C语言指针传递和内存分配
- 从内存分配来看C语言的值传递和指针传递问题
- C语言指针应用——内存分配和释放
- C语言指针的内存分配和Java中的引用
- 指针参数的传递和内存分配
- 浅谈C,C++语言的基本数据类型的内存分配和指针的内存分配
- C语言给指针分配内存
- 转]C语言,指针与内存分配
- [转]C语言,指针与内存分配
- [转]C语言,指针与内存分配
- C语言指针及内存分配
- C语言 指针及动态内存分配
- c语言指针与动态内存分配
- C语言,指针与内存分配
- c语言指针--动态内存分配
- shell脚本内环境变量问题
- DB2 SQL Error: SQLCODE=-418, SQLSTATE=42610, SQLERRMC=unresolved untyped expression,
- linux 网络配置关闭防火墙相关命令的意思
- A*算法解决迷宫问题
- 关于手机插入外置SD卡不能卸载内置SD卡文件
- C语言指针传递和内存分配
- poj2112 Optimal Milking dinic/isap+floyed+二分
- 【php】php中获取任意个参数
- java数据结构之带头结点的单链表
- Struts2 如何获取Request,Session对象
- STL之heap
- [LeetCode][Java] Merge Two Sorted Lists
- BMFont使用
- 机试题目