0%

C 语言指针与指针的指针

这篇文章记述了关于C 语言指针与指针的指针的知识点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void getmemory(char* p)
{
p = (char*)malloc(100);
strcpy(p, "helloworld");
}

int main()
{
char* str = NULL;
getmemory(str);
printf("%s\n", str);
free(str);
return 0;
}

这段代码是学长发给我的,答案说这段代码会导致程序崩溃,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
2
3
4
5
6
7
8
9
10
11
12
13
14
void getmemory(char** p)
{
*p = (char* )malloc(100);
strcpy(*p, "helloworld");
}

int main()
{
char* str = NULL;
getmemory(&str);
printf("%s\n", str);
free(str);
return 0;
}

补充:

image-20200513180844291

C语言的指针

在C语言中字符串常量的本质表示其实是一个地址,这是许多初学者比较难理解的问题。

举个例子:

1
2
3
char  *s ;

s = "China";

为什么可以把一个字符串赋给一个指针变量?他们俩类型不一致啊。。。

其实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;

Welcome to my other publishing channels