字符数组在内存中是如何存储的?

4

我对字符数组的内存地址感到困惑。以下是演示代码:

char input[100] = "12230 201 50";
const char *s = input;
//what is the difference between s and input?

cout<<"s = "<<s<<endl;                    //output:12230 201 50
cout<<"*s = "<<*s<<endl;                  //output: 1

//here I intended to obtain the address for the first element
cout<<"&input[0] = "<<&(input[0])<<endl;  //output:12230 201 50

char数组本身就是一个指针吗?为什么“&”操作符不能给出char元素的内存地址?如何获得单个条目的地址?谢谢!

2个回答

5
在你的最后一行代码中,表达式&(input[0])确实返回了你的字符数组的第一个字符的地址,也就是你的字符数组input的地址。所以你的代码有点起作用。
但输出运算符<<char *进行了重载,并将你的字符数组作为C字符串输出(打印所有字符直到找到一个零字符为止)。
要输出地址,请按以下操作:
void *p = input;
std::cout << "p=" << p << "\n";

谢谢,但我没有观察到使用“\n”打印时有任何区别,但在&前面加上(void*)可以给出地址。 - jwm
1
是的。\n与指针无关,它只是一个换行符。重要的是要打印一个void* - Johannes Overmann
2
@jingweimo "\n" 只是在输出流中输出换行的一种方式。std::endl 输出一个换行符,同时刷新输出缓冲区。手动刷新缓冲区通常不需要,因此许多人更喜欢使用 '\n' 或 "\n"(在某些情况下可能更快)。 - Blastfurnace
@Blast:是的!当你将输出重定向到文件时,速度可能会慢上几个数量级。刷新几乎总是不必要的。std::endl是一个误解,在正常代码中不应该使用。 - Johannes Overmann

0

虽然在大多数情况下,数组可以被视为指向数组中第一个元素的指针,但它们与指针并不相同。从技术上讲 - 数组会衰变为指针

&(input[0]) 返回一个 char*,它有一个重载函数可以打印实际的字符串。要打印地址,您可以使用 static_cast<void*>(&input[0])


2
不,数组不是指向它们的第一个元素的指针。它们会衰变成它们。这并不意味着它们是相同的,即使这可能有助于初学者理解如何使用它们。 - Fureeish
@Fureeish 注意。除了四个例外(sizeof运算符、_Alignof运算符、一元'&'运算符或用于初始化数组的字符串字面值),对数组的访问是通过指向第一个元素的指针进行的。上面的 &(input[0]) 实际上等同于 inputchar*。唯一需要注意的是 &input 将是指向 int [100] 数组的指针。 - David C. Rankin
2
访问并不等同于身份。即使考虑到除了访问之外的其他方面,这个观点仍然成立。 - Fureeish
@David:多维数组怎么办?那就没有指针数组了吗?不是的。数组和指针是非常不同的,只是在某些情况下会退化成指针。 - Johannes Overmann
不是,但它的工作方式完全相同。假设你有int arr[5][5];并访问arr[0]。你所拥有的是一个指向整数数组的指针[5],例如 int (*)[5]。无论你有多少维度,规则总是相同的。现在我不是在质疑数组和指针是否相同,当然它们不同,我要解决的是对数组(或多维数组等)的访问问题。 - David C. Rankin
1
我想删除这个答案,但由于它是被接受的答案,所以无法删除。已更新答案以考虑评论。 - larsmoa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接