这篇文章记述了关于C 语言指针与指针的指针的知识点。
1 | void getmemory(char* p) |
这段代码是学长发给我的,答案说这段代码会导致程序崩溃,getmemory 中的 malloc 不能返回动态内存,free 对 str 操作很危险。
我试着调试了一下,下面复述调试的过程:
1.首先,str 是一个指向 char 类型的指针,在 32 位机器下占用 4 Bytes,在内存 0x00 00 00 3A 到 0x00 00 00 3D 这 32 位区域内存储着NULL的值 (0x0000 0000)
地址:0x00 00 00 3A | 地址:0x00 00 00 3B | 地址:0x00 00 00 3C | 地址:0x00 00 00 3D |
---|---|---|---|
值:00 | 00 | 00 | 00 |
2.传参的时候把 str 传进去,肯定传递的是 0x0000 0000 啊,然后在 getmemory 函数里面进行 malloc 函数分配,将分配的堆空间区域内的100个字节的首地址传递给 p ,这个时候 p 是在栈上的一个区域,先开始值是 0x0000 0000,经过 malloc 之后 p 的值变成分配到的 100 个字节的首地址,我们假设是 0x1111 2222,最后经过 strcpy 函数进行拷贝,将“helloworld”常量字符串(存储在只读存储区)拷贝给 p 所指的 0x1111 2222堆上区域(100 Bytes 只使用了 11 个字节,因为最后还有一个 ‘\0’ )。
3.从 getmemory 函数返回的时候,栈上的 p 自动被释放,然后 str 还是原来的 NULL。
正确的代码如下:
将 str 的地址传递进去就 ok 了
1 | void getmemory(char** p) |
补充:
C语言的指针
在C语言中字符串常量的本质表示其实是一个地址,这是许多初学者比较难理解的问题。
举个例子:
1 | char *s ; |
为什么可以把一个字符串赋给一个指针变量?他们俩类型不一致啊。。。
其实China在编译的时候是放在了常量区,内存布局大概如下图所示:
0x30000 | 0x30001 | 0x30002 | 0x30003 | 0x30004 | 0x30005 |
---|---|---|---|---|---|
C | h | i | n | a | \0 |
C语言中操作字符串是通过它在内存中的存储单元的首地址进行的,这是字符串的终极本质。
char * 与 char a[ ];
char *s;
char a[ ] ;
前面说到 a代表字符串的首地址,而s 这个指针也保存字符串的地址(其实首地址),即第一个字符的地址,这个地址单元中的数据是一个字符,
这也与 s 所指向的 char 一致。
因此可以 s = a;
但是不能 a = s;