我已经检查了很多编程语言(Java,Erlang,python等)但我发现C / C ++很难学习。仅仅因为我觉得它有时候不合理;
EX1:
#include <iostream>
int main() {
int ar1 = {1,2,3};
int *p1 = ar1;
char *msg = "message";
std::cout << "addr: " << p1 << std::endl ;//prints the array address
std::cout << "value: " << *p1 << std::endl ;//prints the first element
std::cout << "addr: " << msg << std::endl ;//prints "message" , wtf why not the addr?how can i get its address?
std::cout << "value: " << *msg << std::endl ;//prints the first character
}
EX2:
#include <iostream>
int main() {
int n1 = 5;
int *p1 = &n1;
int &r1 = *p1; // why not: int &r1 = p1; ,*p1 is NOT an address,p1 is.This does not make any sense...
}
你能解释一下这些例子吗?我不能继续学习Cplusplus而不解决这些问题。
感谢您的时间。
答案 0 :(得分:6)
问题1:
char *msg = "message";
std::cout << "addr: " << msg << std::endl ;
//prints "message" , wtf why not the addr?
这是C语言历史演变的人工制品,其中字符串通常由字符数组或指向此类数组的指针表示。为了支持这一点,<<
有一个重载char const *
,它将它视为指向字符串的指针并打印字符串内容。
通过使用std::string
类来表示字符串,避免混淆,并避免使用C风格的字符串,除非在非常罕见的情况下它们是有用的。
how can i get its address?
您可以将其转换为通用指针:
std::cout << "addr: " << static_cast<void*>(msg) << std::endl;
^^^^^^^^^^^^^^^^^^
问题2:
int n1 = 5;
int p1 = &n1;
那不编译,因为&n1
是一个地址,因此只能用于初始化指针,而不是int
。我猜你的意思是:
int *p1 = &n1;
int &r1 = *p1;
// why not: int &r1 = p1; ,*p1 is NOT an address,p1 is.This does not make any sense...
因为引用不是指针,并且没有使用地址初始化。必须使用(有效)对象初始化引用,并成为该对象的别名。 *p1
是int
类型的对象,因此可用于初始化对int
的引用。
答案 1 :(得分:4)
&
符号可能会让C ++中的新人感到困惑。这是因为&
可以有多种含义。
此:
int* p1 = &n1;
表示取n1的地址并将其存储在指向int的指针中。 p1
是一个指针,其地址为n1
。
此:
int &r1 = *p1;
表示创建一个称为引用的特殊变量类型。 (在C ++中,引用实际上只是其他东西的别名)。 r1被告知为*p1
处的值别名。 *p1
表示跟随指针p1并获取基础值。在这种情况下,我们知道p1
指向n1
,因此我们知道r1
是对n1
的引用。我的意思是:
r1 = 5;
然后
std::cout << n1;
输出为5
&安培;也可以指二元和算子。这是一个完全不同的东西,你在这里没有问。
答案 2 :(得分:2)
问题的很大一部分是你的例子大多是错误的。
第一个例子:
int ar1 = {1,2,3};
int *p1 = ar1;
说实话,这需要;
int ar1[] = {1, 2, 3};
int *p1 = ar1;
在这种情况下,事情很简单:在大多数情况下(包括这个),数组的名称求值为该数组开头的地址(即,您指定给指针的值的类型) 。主要的例外是当您将数组用作sizeof
运算符的操作数时,因此sizeof(ar1)
将给出数组的实际大小(3 *sizeof(int)
),而不是指针的大小。
在你的第二个例子中:
int n1 = 5;
int p1 = &n1;
int &r1 = *p1; // why not: int &r1 = p1; ,*p1 is NOT an address,p1 is.This does not make any sense...
你是对的 - 这没有任何意义,正常运行的编译器不应该按原样编译它。你显然想要的是这样的:
int n1 = 5;
int *p1 = &n1; // p1 is a pointer to int, holding address of n1
int &r1 = *p1; // r1 is a reference to int, referring to what p1 points at (n1).
就印刷品而言,它非常简单:任何类型的印刷方式纯粹是由编写图书馆的人做出的决定。他们认为最有意义的是当你将指针传递给char时,它会假设你想要打印指向的字符串。对于其他指针类型,他们决定打印出指针本身的值。这些都不是关于语言的正确性 - 这只是某人做出的决定,因为这对他们来说是有意义的。
如果你有一个char /指向char的数组并希望打印出地址而不是它所指向的字符,你通常会将它转换为指向void的指针:
char *msg = "message";
std::cout << static_cast<void *>(msg);
至于他们为什么选择这个,我认为这很简单:因为当人们说cout << mystring
时,他们通常希望打印出字符串的内容。这通常仅限于字符串,因为(几乎)每个人都同意如何打印出字符串的内容,但是当涉及到诸如int,double等数组的内容之类的东西时却没有那么多。