【问题标题】:Creates two pointers? char *name[] = {"xxx", "yyy"}创建两个指针?字符 *name[] = {"xxx", "yyy"}
【发布时间】:2014-02-09 08:25:56
【问题描述】:

有人告诉我作为对我上一个 question 的回答

char *name[] = {"xxx", "yyy"}

被编译器改为

char *name[] = {Some_Pointer, Some_Other_Pointer};

我尝试了以下理解:

printf("%p\n", &name);
printf("%p\n", name);
printf("%s\n", *name);
printf("%c\n", **name);

所以它给了我一个输出:

0xfff0000f0
0xfff0000f0
xxx
x

你能解释一下指针“name”的地址如何与指针“name”指向的地址相同吗? 据我了解,指针“名称”本身占用 8 个字节。内存中占4个字节的第一个字符串“xxx”怎么能和指针在同一个位置呢?

【问题讨论】:

    标签: c arrays string pointers


    【解决方案1】:

    首先,当你在 C 中有任何像 name 这样的数组时,数组的 就是它的第一个元素的地址。请注意,此值未存储在某些变量中。它在已编译的汇编代码中用作立即值。所以考虑它的地址是没有意义的。

    其次,由于数组是作为一串连续的位置存储在内存中的,所以数组的地址定义为第一个元素的地址。因此,对于任何数组A,您都具有以下地址相等性

     &(A[0]) == A == &A
    

    如果你有指针数组或其他任何东西,它不会改变任何东西。

    【讨论】:

    • 这是一个很好的解释,谢谢。尽管我还没有完全开悟......我想知道数组“name”的大小如何为 16 个字节(因为它是 2 个指针)并且两个字符串都是 4 个字节长......字符串和指针在哪里位于内存中?
    • 答案是:字符串存储在某处(只读静态分配页面)!那就是编译器决定将它们放置在其放置全局常量的位置。另一方面,指向字符串的两个指针存储在数组中。
    • 所以字符串的地址是 name[0] 和 name[1] ?正如@mahendiran.b 所说:如果我使用 %p 作为格式,我会得到字符串的地址,如果我使用 %s 作为格式,我会得到字符串的值?
    • @Jan: sizeof name 是 16,因为这个答案部分是关于数组的错误。数组的值是它的第一个元素的地址是不正确的。数组的名称确实代表数组,而不是它的值。但是,任何数组表达式(无论是简单名称还是以某种方式计算出来的)都会自动转换为其第一个元素的地址except,如果它是sizeof_Alignof 的操作数或& 或当它是用于初始化数组的字符串文字时。 (此规则在 C 2011 6.3.2.1 3 中。)
    • Eric Postpischil:严格来说你确实是对的。由于问题的程度,我不想进入迂腐的微妙之处。如果我说“评估数组返回其第一个元素的地址”对您来说是否更正确?
    【解决方案2】:

    要查看“xxx”的地址,你应该像这样打印printf("%p\n", name[0]);。一定是name and address of "xxx" wont be the same的地址。这里namearray of pointer,它保存着“xxx 和 yyy”的地址。

    printf("%p\n", &name);
    printf("%p\n", name);
    printf("%p\n", name[0]); address of "xxx"
    printf("%p\n", name[1]); address of "yyy"
    

    【讨论】:

      【解决方案3】:

      你能解释一下指针“name”的地址如何与指针“name”指向的地址相同吗?

      &name 为您提供整个指针数组的地址(其中包含指向字符串XXXYYY 的指针)和name 将为您提供指向其第一个元素的指针,即@987654325 @(衰减后)。由于第一个字节的地址被称为变量(数组)的地址,&name 的值与name 的值相同,但&namename 的类型不同。

      【讨论】:

        【解决方案4】:

        name的类型从array of char*衰减到pointer to char*,其值为数组第一个元素的地址。表达式&namepointer to char* [2] 类型,它的值是数组的地址,与数组的第一个元素的地址相同。

        您似乎误解了 C 中数组的表示。C 中没有表示数组的“元”对象。C 中的数组仅包含其元素的顺序。因此,将运算符 & 应用于数组名称只会让您获得数组第一个元素的地址(值方面,而不是类型方面)。

        如果你尝试写作:

        char (*p)[2] = &name;
        printf("%p", &p);
        

        这会打印出address of a pointer to an array,它肯定会是与name&name 不同的值。

        【讨论】:

          【解决方案5】:

          据我了解,指针“名称”本身占用 8 个字节。如何 内存中占用4个字节的第一个字符串“xxx”可以在 与指针位置相同?

          那是因为name 是一个数组,而不是一个指针。指针是一个变量,它存储另一个相同类型的变量的地址,但数组是一个连续的内存块,绑定到(由)单个标识符。基本上,它是一种不同的类型。请注意,数组不是 C 中的第一类对象——您不能将数组传递给函数或从函数返回数组。

          之所以产生混淆,是因为在许多情况下,数组会衰减(隐式转换)为指向其第一个元素的指针。发生这种情况的一些情况是:

          void f(char p[]); // p is a pointer, not an array
          
          // This is exactly the same as
          
          void f(char *p); 
          
          char s[] = {'h', 'e', 'l', 'l', 'o'};
          f(s);   // here s decays to a pointer to its first element
          
          // another example
          
          char t = "hello"[1]; // the string literal decays to a pointer to its first element
          

          以下是数组保持为数组(不会衰减为指针)的一些情况:

          char s[] = "hello";
          char *t = "hello"; // string literal decays into a pointer
          
          printf("%d", sizeof s);  // prints 5
          printf("%d", sizeof t);  // prints 4 or 8 depending on the pointer size on the machine
          printf("%d", sizeof *t);  // prints 1
          
          // taking your example
          
          char *name[] = {"xxxx", "yyyy"}; // yet another case where string literals decay to a pointer
          
          printf("%p", name); // name is an array but here decays to a pointer
          printf("%p", &name); // &name is a pointer to an array of 2 pointers to characters
          

          虽然name&nameprintf 调用中的计算结果相同,但它们的类型不同。要查看差异,请执行以下操作:

          printf("%p", name + 1);
          printf("%p", &name + 1);
          
          printf("%d", *(&name + 1) - name); // prints the length of the array
          

          总而言之,数组和指针是不同的类型。指针存储地址,数组存储它们定义要存储的类型的值。在某些情况下,数组计算为其第一个元素的地址。这就是数组和指针之间的相似性结束的地方。

          【讨论】:

            猜你喜欢
            • 2012-09-09
            • 1970-01-01
            • 2011-08-09
            • 2019-06-14
            • 1970-01-01
            • 2010-11-06
            • 1970-01-01
            • 1970-01-01
            • 2017-04-12
            相关资源
            最近更新 更多