繁体   English   中英

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

[英]Difference between char* and char** (in C)

我写了这段代码很简单

#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;
}

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

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

char *ptr; 不为字符分配 memory,它为指向 char 的指针分配 memory。

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

用于演示: 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

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

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

char **x 是指向指针的指针,当您想要修改其 scope 之外的现有指针时(例如,在 function 调用中),这很有用。

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

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);
}

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

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

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

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

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

printLastLetter( str ); 

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

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

您可能会关心研究程序的这个微小变化(function printLastLetter()没有变化,只是它被设为静态),并找出 output 的原因:

3
X

output 是完全确定的——但这只是因为我仔细设置了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;
}

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

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

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

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

**str只不过是(*str)[0]以及*strstr[10]之间的区别(在声明中,我假设)我认为前者只是一个指向常量字符串文字的指针可能存储在全局 static memory 中的某处,而后者在存储文字的堆栈上分配 10 个字节的 memory。

char * 是指向 memory 位置的指针。 对于 char * str="123456"; 这是字符串的第一个字符。 "" 只是输入字符值数组的一种便捷方式。 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但不是相反。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM