我已经研究指针一段时间了,我似乎无法完全理解它。当您从解释指针的教程跳到假设您了解它们的实际函数和代码时,似乎有一个差距没有解释。 让我烦恼的代码如下:
char **output_str = malloc(sizeof(char*));
好的,所以我的理解如下,
**output_str is a character
*output_str is a pointer to a character
output_str is a pointer to a pointer to a character
据我所知,malloc() 返回一个指向刚刚分配的内存开头的指针,该指针的大小值等于指向字符(char*)的指针的大小。现在,指向内存开头的指针不应该有一个 * 吗?如果是这样,我们如何将带有 * 的东西分配给 **?我很困惑,如果有人可以提供一些澄清,也许对内存部分有一些见解,那会非常好。
您的代码块是正确的。有了这个声明:
char **output_str = malloc(sizeof(char*));
output_str 是指向 char 指针的 char 指针,或者它可以被视为字符的 2d 数组或字符矩阵。
图形表示:
Memory Address | Stored Memory Address Value
----------------------------------------------
0 | .....
1 | .....
2 | .....
3 | .....
4 | .....
5 | .....
6 | .....
. | .....
. | .....
. | .....
n-1 | .....
将内存想象成一个非常大的数组,您可以在其中通过其内存地址访问位置(在本例中,我们将地址简化为自然数。实际上它们是十六进制值)。"n"是内存的总量(或大小)。由于内存计数并从 0 开始,因此大小等效于 n-1。
1. 当您调用:
char **output_str = malloc(sizeof(char*));
操作系统和 C 编译器为我们完成了这项工作,但我们可以认为我们的内存已经更改。 例如,内存地址 3 现在有一个指向名为output_str
的字符指针的字符指针。
Memory Address | Name - Stored Memory Address Value (it points to ...)
-----------------------------------------------------
0 | .....
1 | .....
2 | .....
3 | output_str = undefined
4 | .....
5 | .....
6 | .....
. | .....
. | .....
. | .....
n-1 | .....
2. 现在如果我们说:
*output_str = malloc(sizeof(char));
内存再次更改。例如,内存地址 0 现在有一个名为*output_str
的字符指针。
Memory Address | Name - Stored Memory Address Value (it points to ...)
-----------------------------------------------------
0 | *output_str = undefined
1 | .....
2 | .....
3 | output_str = 0
4 | .....
5 | .....
6 | .....
. | .....
. | .....
. | .....
n-1 | .....
3. 我们声明一个静态实例化的字符:
char a = 'a';
所以我们的记忆又发生了变化,它被放置在 MemoryAddress[6] = 'a':
Memory Address | Name -> Stored Memory Address Value (it points to ...)
------------------------------------------------------
0 | *output_str = undefined
1 | .....
2 | .....
3 | output_str = 0
4 | .....
5 | .....
6 | a = 'a' // 'a'is static memory
. | .....
. | .....
. | .....
n-1 | .....
最后,我们调用
*output_str = &a;
我们现在告诉 char 指针*output_str
指向/引用先前实例化的char a
。
所以我们最后的记忆将是这样的:
Memory Address | Name - Stored Memory Address Value (it points to ...)
-----------------------------------------------------
0 | *output_str = 6
1 | .....
2 | .....
3 | output_str = 0
4 | .....
5 | .....
6 | a = 'a' // 'a'is static memory
. | .....
n-1 | .....
更多信息
Now printf("Value: " + a) will output "Value: a" printf("Value: " + *output_str[0]) will also output "Value: a" And printf("Value: " + **output_str) will output "Value: a"
这是一个真正的疑问。我会尽力为你说清楚。 从您问题中的详细信息来看,我假设(阅读,"非常确定")您了解malloc
内存和相应的返回类型。
你有一个疑问,如果malloc
返回一个指针(void*
),它怎么能转换为指针到指针(char**
)。
char **output_str
等效于char *(*output_str)
这意味着*output_str
是指向某些类型char
数据的指针。所以,这就是malloc
回归它的内容。- 同样,您会看到
malloc
返回指针。但本质上,你有一个分配给字符(char*
)的指针的内存,"字面上"的意思是,malloc
返回一个指针(void*
)到你char*
的内存,这使得它成为一个指向char
的指针,即char**
。
可以将output_char视为指向字符串数组的指针,每个字符串都是指向字符数组的指针。当你执行malloc(sizeof(char*))时,你只提供一个长度为1的char指针数组,所以*output_char包含一个未初始化的指针(NULL)。
你应该做的是分配足够的指针,以便你可以指向一堆字符串。假设您要存储 N 个字符串,所有字符串都由 output_char 引用。将其初始化为:
// Allocate an array of N string pointers
char **output_str = malloc(sizeof(char*)*N);
然后,您需要为每个字符串分配存储:
// Allocate storage for each of the N strings, assume 80 chars max each
// including the null character required at the end of the string
#define MAX_STRING_SIZE 80
int i;
for(i=0; i<N; i++)
// Allocate storage for each of the strings, but they
// still need to have some chars written to this storage
// for these strings to be anything but null strings ""
output_str[i] = malloc(MAX_STRING_SIZE*sizeof(char));
在每个 C 程序的开头都有一个很好的例子:
int main(int argc, char** argv) { /* your code */ }
每个C程序都以这个主要定义开始。它接受两个参数,一个是通过命令行传递到程序中的字符串数(包括程序本身的名称),argv 是对字符串参数数组的引用。
例如,使用以下命令行参数调用 myprog:
myprog -h "Fred" Jones
导致 main() 被传递argc 和 argv,使得:
argc = 4
argv[0] = "myprog"
argv[1] = "-h"
argv[2] = "Fred"
argv[3] = "Jones"
malloc()
返回可以隐式转换为任何其他指针类型的void *
。在您的情况下,malloc()
分配的空间可以用作char *
值的存储。检查以下示例
char str[10]= {'a'};
//char c = 'c';
char **output_str = malloc(sizeof(char*));
*output_str = str; /* Stored address of a char array of size 10*/
//*output_str = &c; // Stored address of a char, its also correct
printf("%cn",**output_str); /* Will print the char element, if you are using string address it will print first element,
to print other elements in str use (*output_str)[index] */
理解malloc的简单解决方案:
malloc(sizeof(Each_Element) *Number_Of_Elements) 返回新缓冲区的地址(又名:指针)。在这个缓冲区中,每个元素都有相同的大小:sizeof(Each_Element),并且有Number_Of_Elements个元素。
例如:
malloc(sizeof(char))返回一个 char 的指针。
malloc(sizeof(char) * 3)返回一个 char 的指针,该指针是 char 数组的第一个元素包含 3 个字符。
malloc(sizeof(char *) * 6)返回一个 char 指针的指针,该指针是 char 指针数组的第一个元素,包含 6 个 char 指针。
基本上,malloc(sizeof(WHAT)) 返回一个 WHAT 的指针。所以简单地理解:malloc(Sizeof(WHAT)) 返回(WHAT *)。malloc(Sizeof(WHAT *)) 返回(WHAT **)...等等。
请注意,实际上 malloc 返回一个(void *)指针。(Void *)指针稍后可以强制转换为任何类型的指针。所以对于 VisualStudio 用户来说,有一个好方法:int *pbuff = (int *) malloc(sizeof(int) * 6);函数malloc之前的(int *)将"变形虫指针"(void *)转换为(int *)。