【问题标题】:char **s versus char *s[], when and how to use each one?char **s 与 char *s[],何时以及如何使用每一个?
【发布时间】:2011-10-10 13:29:53
【问题描述】:

如果我使用 char *s[],我可以执行以下操作:

char *s[] = {"foo", "bar", "foobar", "whatever", "john", "doe"};

**s 有什么区别?在这种情况下如何使用char **s 而不是char *s[]

示例:int main (int argc, char **argv) 而不是 *argv[]

【问题讨论】:

  • Marcelo,如果答案解决了问题或要求进一步澄清,请不要忘记将答案标记为已接受。

标签: c pointers char


【解决方案1】:

据我所知,**s 是 s 的地址,其中 *s[] 是数组 s 的地址,我认为你会在 s 中存储单个值,但在 s[] 中你会存储数组,而数组本身就是一个指针。希望这会有所帮助!

【讨论】:

  • 不,对于双指针,您可以存储单个值,但它更可能是一个数据块或指向块的指针块
  • 我的意思是它指向数组,而不是那个数组是指针,我对那个不好。
【解决方案2】:

对于函数参数,没有区别。

否则:

char *s[];

s 是一个指向 char 的指针数组。和

char **s;

s 是指向 char 的指针。

如果需要指向 char 的指针数组,则使用前者,如果需要指向 char 的指针,则使用后者。

【讨论】:

    【解决方案3】:

    如果你定义了

    char **s[] = {"foo", "bar", "foobar", "whatever", "john, "doe"};
    

    我认为这和定义三维数组(char s[10][10][10])是一样的,因为 char *s[] 是定义一个二维数组。

    【讨论】:

      【解决方案4】:

      它们创建相同的数据结构。唯一的区别是 char*s[] 在初始化时自动为{"foo", "bar", "foobar", "whatever", "john, "doe"} 分配足够的内存。 char **s 只会为指针分配一个字节,然后您需要自己手动为数组中的每个字符串分配内存。

      【讨论】:

        【解决方案5】:

        当您使用char *s[] = {"foo", "bar", "foobar", "whatever", "john, "doe"}; 时,编译器已经知道数组的长度,即:在这种情况下,它知道它是指向 6 个字符数组指针的指针。

        char** 缺少长度信息,这就是为什么 main 有 2 个参数 {length, pointer to pointer to char} == {argc, arv}

        【讨论】:

          【解决方案6】:

          作为函数参数,没有任何区别。它们是等价的。

          void f(int** p);
          void f(int* p[]);
          void f(int* p[42]);
          

          这三个声明是等价的。

          作为对象,它们有不同的类型;

          char *s[] = {"foo", "bar", "foobar", "whatever", "john, "doe"};
          

          s6 指向 char 的指针数组 sizeof(s) == 6*sizeof(void*)

          char **s;
          

          s 是指向char 的指针。 sizeof(s) == sizeof(void*)

          【讨论】:

          • +1 以获得简洁的答案。次要问题(它不应该有所作为):您应该使用 sizeof(char *) 而不是 void *
          • @tomlogic:我用void*来强调所有指针的大小相同,一个是指针,另一个是指针数组(不管是什么指针)。
          • @Armen:不完全是:stackoverflow.com/questions/1241205/…。尽管如此,char *void * 具有相同的大小和表示形式。
          【解决方案7】:

          数组和指针是不同的东西。指针可用于访问数组中的元素。为了能够初始化一个数组,你需要声明一个数组,而不是一个指针。

          要清楚地显示差异,试试这个:

          int[] ia = {1, 2, 3, 4, 5, 6, 7, 8};
          int* ip = ia;
          
          printf("sizeof(ia): %zu, sizeof(ip): %zu", sizeof(ia), sizeof(ip));
          

          第一个应该打印数组的大小,第二个应该打印一个 int 指针的大小。

          C 的奇怪之处在于,当数组作为参数传递给函数时,它会衰减为指针。在http://www.lysator.liu.se/c/c-faq/c-2.html 的第 2.3 节中查看更多信息。 main 接受argv** 而不是argv*[] 的原因是argv*[] 在作为函数参数传递时会衰减为argv**

          【讨论】:

            【解决方案8】:

            不是直接回答你的问题,但这可能有助于你了解更多:

            #include <stdio.h>
            #include <string.h>
            
            int main() {
            
                char *s[] = {"foo", "bar", "foobar", "whatever", "john", "doe"};
            
                printf("  s[0]: %s \n", s[0]);
                printf("    *s: %s \n", *s);
                printf("  *s+1: %s \n", *s+1);
                printf("*(s+1): %s \n", *(s+1));
            
            return 0;
            }
            

            输出:

            $ gcc -o chararr chararr.c 
            $ ./chararr 
              s[0]: foo   
                *s: foo 
              *s+1: oo 
            *(s+1): bar 
            

            【讨论】:

              【解决方案9】:

              这取决于您的要求。如果您的程序以后不必修改这些字符串,您可以使用

              char *s[] = {"foo", "bar", "foobar", "whatever", "john", "doe"};
              

              这些在只读部分编译为字符串文字。

              汇编输出:

                      .file   "test.c"
                      .section        .rodata
              .LC0:
                      .string "foo"
              .LC1:
                      .string "bar"
              .LC2:
                      .string "foobar"
              .LC3:
                      .string "whatever"
              .LC4:
                      .string "john"
              .LC5:
                      .string "doe"
                      .text
              

              如果您稍后在程序中尝试修改这些字符串,您会遇到分段错误。在这种情况下,您必须使用char **s

              【讨论】:

              • 如何用 char **s 分配(即 6 个)单词?
              猜你喜欢
              • 2010-12-14
              相关资源
              最近更新 更多