C ++中的以下程序打印的输出超出了我的预期。任何人都可以解释为什么会这样吗?该程序试图使用指针循环遍历整数数组,沿途打印每个值。
#include <cstdio>
using namespace std;
int main(int argc, char **argv) {
puts("hi");
int ia[5] = {1,2,3,4,5};
for (int *p = ia; *p; ++p) {
printf("Char is: %d\n", *p);
}
return 0;
}
/*
hi
Char is: 1
Char is: 2
Char is: 3
Char is: 4
Char is: 5
Char is: 32767
Char is: -811990796
Char is: -133728064
Char is: 1606416320
Char is: 32767
Char is: -1052593579
Char is: 32767
Program ended with exit code: 0
*/
答案 0 :(得分:4)
你需要有一个0 / NULL值才能停止,目前你没有。
你的循环条件将允许迭代,直到你得到一个计算结果为false的值(即0)并且你的数组不包含它,所以你的迭代将继续超过数组的边界并且在某些时候退出它访问一些不应该的内存。
有几种方法可以解决它。您可以在数组的末尾添加0。
#include <cstdio>
using namespace std;
int main(int argc, char **argv) {
puts("hi");
int ia[] = {1,2,3,4,5, 0};
for (int *p = ia; *p; ++p) {
printf("Char is: %d\n", *p);
}
return 0;
}
问题是你现在不能在数组中使用0,否则它会提前终止。
更好的方法是在给定数组长度的情况下预先计算停止的地址。这个地址是数组末尾的地址。
#include <cstdio>
using namespace std;
int main(int argc, char **argv) {
puts("hi");
int ia[] = {1,2,3,4,5};
int* end = ia + 5;
for (int *p = ia; p != end; ++p) {
printf("Char is: %d\n", *p);
}
return 0;
}
现在我们开始研究标准库迭代器使用的方法。现在模板可以推断出数组的大小。
即
#include <iterator>
...
for (auto it = begin(ia); it != end(ia); ++it) {
printf("Char is: %d\n", *it);
}
...
答案 1 :(得分:2)
任何人都可以解释为什么会这样吗?
您正在访问数组越界。您的程序有不确定的行为。
该行
int ia[5] = {1,2,3,4,5};
创建一个包含5个元素的数组。 1}}在访问数组的最后一个元素后访问*p
并不好。
您可以使用:
for (int *p = ia; p != std::end(ia); ++p) {
确保您不会超出界限访问数组。
您需要添加:
#include <iterator>
使用std::end
。
答案 2 :(得分:1)
或者使用sizeof()
运算符来确定元素的数量:
for (int *p = ia; p < ia + sizeof(ia)/sizeof(*ia); ++p) {
printf("Char is: %d\n", *p);
}
答案 3 :(得分:0)
实际上是条件:
for( ; *p; )//...
将检查地址中的值是否等于0,因此仅当值为零时才会停止,当然这不是您想要的;你想增加地址直到最后一个元素,但是你的代码在lat元素不为NULL之后检查地址内的值而不是地址本身的地址本身。
要解决您的问题,您可以计算数组中的元素数量,然后在循环内部相应地增加指针:
#include <cstdio>
using namespace std;
int main(int argc, char **argv) {
puts("hi");
int ia[5] = {1,2,3,4,5};
int* end = &ia[0] + 4;
for (int *p = ia; p <= end; ++p) {
printf("Char is: %d\n", *p);
}
return 0;
}