考虑以下代码:
double *pi;
double j;
pi = &j;
pi[3] = 5;
我不明白我怎么可能在这里执行最后一行。 我将pi设置为j的引用,这是一个双变量,而不是double []变量。那么我怎么可能在它上面执行数组命令呢?
考虑以下代码:
char *c = "abcdefg";
std::cout << &(c[3]) << endl;
输出是“defg”。我希望我会得到一个参考输出,因为我使用了&amp;,但是我得到了从单元格位置到结尾的char *的值。那是为什么?
答案 0 :(得分:1)
这里有两个不同的问题。
指针有时用于指向内存中的数组或缓冲区。因此它支持[]
语法。在这种情况下,使用pi[x]
,其中x不为0是无效的,因为您没有指向数组或缓冲区。
Streams对char
指针有一个重载,将它们视为C风格的字符串,而不是输出它们的地址。这就是你的第二种情况。试试std::cout << static_cast<const void *>(&(c[3])) << endl;
答案 1 :(得分:0)
指针和数组在C中相辅相成(有点......)
pi[3]
与*(pi + 3)
相同。但是,在您的代码中,当您在对象边界外创建指针时,这会导致未定义的行为。
另外要小心,因为*
和&
是不同的运算符,具体取决于出现的表达式。
答案 2 :(得分:0)
这是未定义的行为。 C ++允许你做你不应该做的事情。
char*
有一些特殊规则,因为它通常用作字符串的开头。如果将char*
传递给cout
,它会打印任何指向字符的内容,并在达到'\ 0'时停止。
答案 3 :(得分:0)
好的,这里有一些主要内容:
指针就是它,它指向内存中的一个位置。因此,如果你想要,指针可以是一个数组。
如果你正在使用指针(有时是危险的),这会使事情复杂化。你正在写p,这是一个指向内存位置的指针。因此,即使您尚未分配内存,也可以将内存作为数组进行访问并进行编写。但这给了我们你提出的问题。怎么会这样?好吧,简单的答案是你正在访问一个内存区域,你所创建的变量完全没有控制权,所以你可能会踩到另一个变量(如果你有其他变量)或者只是写在尚未存在的内存上已经使用了。
在第二个问题中,我不明白你在问什么,也许你可以解释一下?感谢。
答案 4 :(得分:0)
此代码的最后一行......
double *pi;
double j;
pi = &j;
pi[3] = 5;
...是(pi + 3)= 5的句法等价物。编译器如何查看double []变量和double 变量没有区别。
虽然上面的代码会编译,但会导致内存错误。这是安全的代码,说明了相同的概念......
double *pi = new double[5]; // allocate 5 places of int in heap
double j;
pi[3] = 5; // give 4th place a value of 5
delete pi; // erase allocated memory
pi = &j; // now get pi to point to a different memory location
答案 5 :(得分:0)
我不明白我怎么可能执行最后一次 在这里。我将pi设置为j
的引用
实际上,您正在设置指针 pi,指向j的内存地址。
当你做pi [3]时,你使用非数组变量作为数组。虽然有效的c ++,但它本质上是危险的。您可能会覆盖其他变量的内存,甚至访问进程外部的内存,这将导致操作系统终止您的程序。
如果说的话,pi [3]意味着你说“给我从pi的记忆位置下来第三个位置”。所以你不是触摸pi本身,而是一个偏移。
如果要使用数组,请将它们声明为:
double pi[5]; //This means 5 doubles arrayed aside each other, hence the term "array".
Appropos数组,在c ++中通常最好不使用原始数组,而是使用向量(还有其他类型的容器):
vector<double> container;
container.push(5.25); //"push" means you add a variable to the vector.
与原始数组不同,像vector这样的容器会在内部保持它的大小,所以如果你在其中放入5个双打,你可以调用container.size(),它将返回5.有用于for循环和之类的。
关于你的第二个问题,你实际上是在返回对“abcdefg”字符串的子字符串的引用。
&amp;([3])的意思是“给我一个字符串,从d开始”。由于c风格的字符串(调用char *)会在末尾添加一个额外的NULL,任何将这些作为参数(例如cout)的代码都将继续读取内存,直到它们偶然发现NULL(也就是0) )。 NULL终止字符串,这意味着它标记数据的结尾。
Appropos,c风格的字符串是唯一表现得像数组的数据类型,实际上并不是一个。这也意味着它们很危险。就个人而言,我从来没有任何需要使用它。我建议使用现代字符串。这些更新的,特定于c ++的变量既安全又易于使用。像矢量一样,它们是容器,它们跟踪它们的大小,并且它们自动调整大小。观察:
string test = "abcdefg";
cout<<test.size()<<endl;//prints 7, the number of characters in the array.
test.append("hijklmno");//appends the string, AND updates the size, so subsequent calls will now return 15.