C中的双星号和`malloc`

时间:2017-03-22 03:34:38

标签: c pointers types malloc

我一直在研究指针,我似乎无法完全绕过它。当您从解释指向实际函数的指南和假设您了解它们的代码跳转时,似乎存在一个无法解释的差距。 令我烦恼的代码如下:

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 *)的指针的大小。现在,不应该指向内存开始的指针有一个*?如果是这样,我们怎样才能为*分配*?我很困惑,如果有人能提供一些澄清,并且可能对内存部分有一些了解,那将非常好。

5 个答案:

答案 0 :(得分:4)

您的代码块是正确的。有了这个声明:

  

char **output_str = malloc(sizeof(char*));

output_str是一个指向char指针的char指针,或者它可以看作是char的2d数组,或者是char的矩阵。

以图形方式表示:

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现在有一个 char指针指向一个名为output_str的char指针

    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:

  

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" 

答案 1 :(得分:2)

这是一个真正的怀疑。我会尽力为你说清楚。 根据你问题中的细节,我假设(阅读,“非常确定”)你理解malloc内存和相应的返回类型。

您怀疑如果malloc返回指针(void*),它如何转换为指向指针(char**)的指针。

  1. char **output_str相当于char *(*output_str),这意味着*output_str是指向char类型数据的指针。所以,这就是malloc返回它的原因。
  2. 再次,您看到malloc返回一个指针。但实际上,你有一个指向char(char*)的指针的已分配内存,“字面意思”意味着,malloc正在将指针(void*)返回到你拥有的内存中char*,它是指向char指针的指针,即char**

答案 2 :(得分:0)

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("%c\n",**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] */

答案 3 :(得分:0)

将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"

答案 4 :(得分:0)

理解malloc的简单解决方案:

malloc(sizeof( Each_Element )* Number_Of_Elements )返回新缓冲区的地址(又名:指针)。在此缓冲区中,每个元素都具有相同的大小:sizeof( Each_Element ),并且有 Number_Of_Elements 元素。

例如:

malloc(sizeof(char))返回char的指针。

malloc(sizeof(char)* 3)返回char的指针,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 *)转换&#34; Amoeba指针&#34; (void *)进入(int *)