4

我创建了一个程序,该程序创建了三个 c 字符串,然后是一个指针数组,其大小与我创建的 c 字符串数量相同 (3),数组中的每个指针都指向三个字符串中每个字符串的第一个字符,最后是指向指针数组的指针(将指向数组中的第一个指针)。

这是代码:

    int main() {
    char arr1 [] = "hello";
    char arr2 [] = "dear";
    char arr3 [] = "world";

    char* p1[3];
    *p1 = arr1;
    *(p1+1) = arr2;
    *(p1+2) = arr3;
    char** ptr = p1;
}

但是,当我执行类似的操作时,std::cout << *ptr << std::endl;我希望它只输出指针数组中第一个指针的地址。然而,它实际上打印出了整个单词"hello",这对我来说似乎很奇怪。我希望有一个地址,如果我输出**ptr了,我希望它只打印出这封信"h"(它实际上是这样)我是否理解不正确?如果我做了同样的事情std::cout << *(ptr+1)..我希望指针数组中第二个指针的地址p1,但它实际上打印出整个单词“亲爱的”。我很迷茫..我认为取消引用ptr会给我地址p1,两次取消引用会给我地址内的值p1

4

3 回答 3

3

您看到的“异常”与指针无关,而是与<< operator.

std::cout << *ptr << std::endl;

相当于

std::cout << arr1 << std::endl;

因此重载 << 运算符:

ostream& operator<< (ostream& os, const char* s);

叫做。arr1衰减到const char* ss被视为 C 字符串并打印到 '\0'

于 2013-09-19T06:56:23.500 回答
3

如果你想打印出指针,你应该把它转换为 void 指针:

cout << (const void*) *ptr << endl;

因为 char * 实际上是旧式 C 字符串,并且有一个重载函数:

std::ostream& operator << (std::ostream&, const char *);

输出字符串而不是指针地址。对于其他指针,它应该可以正常工作。

于 2013-09-19T06:50:55.177 回答
1

也可能相关:char* - 为什么指针中没有地址?

正如人们所说,你遇到的问题是你正在击中

ostream& operator<<(ostream& o, const char* str);

输出运算符将为您打印 c 字符串,如果您将其转换为void*它,它将按照您的预期打印地址。据我所知,你已经正确理解了。您可以想到指向指针的指针的一种方法是数组数组,考虑到这一点,您的示例可以重写为类似这样的内容(但这并不完全等效):

int main() {
char arr1 [] = "hello";
char arr2 [] = "dear";
char arr3 [] = "world";

char p1[3][10];
p1[0] = arr1; //or *(p1+1) = arr1
p1[1] = arr2; //or *(p1+2) = arr2
p1[2] = arr3; //or *(p1+3) = arr3
char** ptr = p1;
}

我选择 10 只是为了能够容纳最长的字符串和一些额外的字符。这在内存中看起来像这样:

hello\0----dear\0-----world\0----
^          ^          ^
|          |          |
|          |          arr3,ptr[2]
|          arr2,ptr[1]
*ptr/ptr[0], arr1    

破折号只是乱码数据,可以是任何数据,因为我们为char p1[3][10];. 希望这张图片能提供更多关于它的外观和指针去向的信息。虽然,如果我们习惯于malloc()创建这个结构,我们可以用几种不同的方式来完成它,例如:

char* a = (char*)malloc(10*sizeof(char));
char* b = (char*)malloc(10*sizeof(char));
char* c = (char*)malloc(10*sizeof(char));
strcpy(a, "hello");
strcpy(b, "dear");
strcpy(c, "world");
char** ptrs = (char**)malloc(3*sizeof(char*)); //3 pointers, ie: char* ptr[3];
ptrs[0] = a;
ptrs[1] = b;
ptrs[2] = c;

这可能看起来像这样:

ptrs:---|, --|, ------|
        v    v        v
        a-\  b-----\  c----\
          v        v       v
         "hello"  "dear"  "world"

即:它们不会再排成一条长线,但我们分配的每一件东西都会在它自己的位置上。指向 a、b 和 c 的指针也是如此ptrs,而它们又指向字符串“hello”、“dear”和“world”的开头。因此,如果我们取消引用ptrs( *ptrs),我们将获得一个指向a(achar*因为我们取消引用 a char**) 的指针,它是指向“hello”中第一个字母的指针。当它被发送给cout它时,它会找到前面提到operator<<的 c 字符串,因此打印出它找到的字符串。这里可能要提到的重要一点是,*ptrs它等同于,ptrs[0]但您似乎已经掌握了这一点。

希望我没有通过向您提供虚假信息而完全搞砸了这件事,如果有人发现有问题或者我完全弄错了,请告诉我,以便我可以像其他人所做的那样删除它 x)我也希望这样做它以某种方式更清楚,请询问是否有任何不清楚的地方。

于 2013-09-19T07:48:11.363 回答