C语言 char* 和 char** 之间的区别(在 C 中)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7065277/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 09:24:02  来源:igfitidea点击:

Difference between char* and char** (in C)

cstringpointers

提问by yotamoo

I have written this code which is simple

我写了这段代码,很简单

#include <stdio.h>
#include <string.h>

void printLastLetter(char **str)
{
    printf("%c\n",*(*str + strlen(*str) - 1));
    printf("%c\n",**(str + strlen(*str) - 1));
}

int main()
{
    char *str = "1234556";
    printLastLetter(&str);
    return 1;
}

Now, if I want to print the last char in a string I know the first line of printLastLetter is the right line of code. What I don't fully understand is what the difference is between *str and **str. The first one is an array of characters, and the second?? Also, what is the difference in memory allocation between char *str and str[10]? Thnks

现在,如果我想打印字符串中的最后一个字符,我知道 printLastLetter 的第一行是正确的代码行。我不完全理解的是 *str 和 **str 之间的区别。第一个是字符数组,第二个是?? 另外,char *str 和 str[10] 之间的内存分配有什么区别?谢谢

回答by MByD

char*is a pointer to char, char **is a pointer to a pointer to char.

char*是一个指向char的指针,char **是一个指向char指针的指针。

char *ptr;does NOT allocate memory for characters, it allocates memory for a pointer to char.

char *ptr;不为字符分配内存,而是为指向字符的指针分配内存。

char arr[10];allocates 10 characters and arrholds the address of the first character. (though arris NOT a pointer (not char *) but of type char[10])

char arr[10];分配 10 个字符并arr保存第一个字符的地址。(虽然arr不是指针(不是char *)而是类型char[10]

For demonstration: char *str = "1234556";is like:

为了演示:char *str = "1234556";就像:

char *str;         // allocate a space for char pointer on the stack
str = "1234556";   // assign the address of the string literal "1234556" to str

As @Oli Charlesworthcommented, if you use a pointer to a constant string, such as in the above example, you should declare the pointer as const- const char *str = "1234556";so if you try to modify it, which is not allowed, you will get a compile-time error and not a run-time access violation error, such as segmentation fault. If you're not familiar with that, please look here.

正如@Oli Charlesworth评论的那样,如果您使用指向常量字符串的指针,例如在上面的示例中,您应该将指针声明为const-const char *str = "1234556";所以如果您尝试修改它,这是不允许的,您将获得编译时错误而不是运行时访问冲突错误,例如分段错误。如果您对此不熟悉,请看这里

Also see the explanation in the FAQ of newsgroup comp.lang.c.

另请参阅新闻组 comp.lang.c 的常见问题解答中的说明

回答by James O'Doherty

char **x is a pointer to a pointer, which is useful when you want to modify an existing pointer outside of its scope (say, within a function call).

char **x 是一个指向指针的指针,当您想修改其范围之外的现有指针时(例如,在函数调用中),这很有用。

This is important because C is pass by copy, so to modify a pointer within another function, you have to pass the address of the pointer and use a pointer to the pointer like so:

这很重要,因为 C 是通过复制传递的,因此要在另一个函数中修改指针,您必须传递指针的地址并使用指向该指针的指针,如下所示:

void modify(char **s)
{
  free(*s); // free the old array
  *s = malloc(10); // allocate a new array of 10 chars
}

int main()
{
  char *s = malloc(5); // s points to an array of 5 chars
  modify(&s); // s now points to a new array of 10 chars
  free(s);
}

You can also use char ** to store an array of strings. However, if you dynamically allocate everything, remember to keep track of how long the array of strings is so you can loop through each element and free it.

您还可以使用 char ** 来存储字符串数组。但是,如果您动态分配所有内容,请记住跟踪字符串数组的长度,以便您可以遍历每个元素并释放它。

As for your last question, char *str; simply declares a pointer with no memory allocated to it, whereas char str[10]; allocates an array of 10 chars on the local stack. The local array will disappear once it goes out of scope though, which is why if you want to return a string from a function, you want to use a pointer with dynamically allocated (malloc'd) memory.

至于你的最后一个问题, char *str; 简单地声明一个没有分配内存的指针,而 char str[10]; 在本地堆栈上分配一个 10 个字符的数组。但是,一旦超出范围,本地数组就会消失,这就是为什么如果您想从函数返回字符串,您想使用动态分配(malloc'd)内存的指针。

Also, char *str = "Some string constant"; is also a pointer to a string constant. String constants are stored in the global data section of your compiled program and can't be modified. You don't have to allocate memory for them because they're compiled/hardcoded into your program, so they already take up memory.

另外, char *str = "Some string constant"; 也是一个指向字符串常量的指针。字符串常量存储在已编译程序的全局数据部分,不能修改。您不必为它们分配内存,因为它们已编译/硬编码到您的程序中,因此它们已经占用了内存。

回答by Jonathan Leffler

You might care to study this minor variation of your program (the function printLastLetter()is unchanged except that it is made static), and work out why the output is:

您可能想研究程序的这个微小变化(该函数printLastLetter()没有变化,只是它被静态化了),并找出为什么输出是:

3
X

The output is fully deterministic - but only because I carefully set up the listvariable so that it would be deterministic.

输出是完全确定的——但这只是因为我仔细设置了list变量,使其具有确定性。

#include <stdio.h>
#include <string.h>

static void printLastLetter(char **str)
{
    printf("%c\n", *(*str + strlen(*str) - 1));
    printf("%c\n", **(str + strlen(*str) - 1));
}

int main(void)
{
    char *list[] = { "123", "abc", "XYZ" };
    printLastLetter(list);
    return 0;
}

回答by stacker

The first one is an array of characters, and the second??

第一个是字符数组,第二个是??

The second is a pointer to your array. Since you pass the adress of str and not the pointer (str) itself you need this to derefence.

第二个是指向数组的指针。由于您传递的是 str 的地址而不是指针 (str) 本身,因此您需要使用它来取消引用。

printLastLetter( str ); 

and

printf("%c\n",*(str + strlen(str) - 1)); 

makes more sense unless you need to change the value of str.

除非您需要更改 str 的值,否则更有意义。

回答by Shamim Hafiz

for your code snippet, *strholds address to a char and **strholds address to a variable holding address of a char. In another word, pointer to pointer.

对于您的代码片段,*str将地址保存到字符并将**str地址保存到字符的变量保存地址。换句话说,指针指向指针。

Whenever, you have *str, only enough memory is allocated to hold a pointer type variable(4 byte on a 32 bit machine). With str[10], memory is already allocated for 10 char.

每当您有 *str 时,只会分配足够的内存来保存指针类型变量(32 位机器上的 4 字节)。使用 时str[10],已经为 分配了内存10 char

回答by Christian Rau

**stris nothing else than (*str)[0]and the difference between *strand str[10](in the declaration, I assume) I think is, that the former is just a pointer pointing to a constant string literal that may be stored somewhere in global static memory, whereas the latter allocates 10 byte of memory on the stack where the literal is stored into.

**str不是别的(*str)[0]之间的差异*str,并str[10](在声明中,我认为),我认为是,前者是全球静态存储器只是指向一个常量字符串文字,一个指针可以存储的地方,而后者则分配10字节存储文字的堆栈上的内存。

回答by John Humphreys - w00te

char** is for a string of strings basically - an array of character arrays. If you want to pass multiple character array arguments you can use this assuming they're allocated correctly.

char** 基本上是用于字符串的字符串 - 字符数组的数组。如果你想传递多个字符数组参数,你可以使用这个假设它们被正确分配。

char **x; *x would dereference and give you the first character array allocated in x. **x would dereference that character array giving you the first character in the array.

字符**x; *x 将取消引用并为您提供在 x 中分配的第一个字符数组。**x 将取消引用该字符数组,为您提供数组中的第一个字符。

回答by QuentinUK

char * is a pointer to a memory location. for char * str="123456"; this is the first character of a string. The "" are just a convenient way of entering an array of character values. str[10] is a way of reserving 10 characters in memory without saying what they are.(nb Since the last character is a NULL this can actually only hold 9 letters. When a function takes a * parameter you can use a [] parameter but not the other way round.

char * 是指向内存位置的指针。对于 char * str="123456"; 这是字符串的第一个字符。"" 只是一种输入字符值数组的便捷方式。str[10] 是一种在内存中保留 10 个字符而不说明它们是什么的方法。(nb 由于最后一个字符是 NULL,这实际上只能容纳 9 个字母。当函数采用 * 参数时,您可以使用 [] 参数但不是反过来。

You are making it unnecessarily complicated by taking the address of str before using it as a parameter. In C you often pass the address of an object to a function because it is a lot faster then passing the whole object. But since it is already a pointer you do not make the function any better by passing a pointer to a pointer. Assuming you do not want to change the pointer to point to a different string.

通过在将 str 用作参数之前获取它的地址,您使其变得不必要地复杂化。在 C 中,您经常将对象的地址传递给函数,因为它比传递整个对象要快得多。但是由于它已经是一个指针,因此您不能通过将指针传递给指针来使函数变得更好。假设您不想将指针更改为指向不同的字符串。