请解释:for循环之后跳过行?

时间:2012-06-17 15:21:38

标签: c++ control-flow

我正在尝试使用C ++完成我的第一个步骤。

有人可以解释为什么这不符合我的预期吗?

#include <iostream>
#include <stdio.h>

using namespace std;

int main (int argc, char *argv[]) {
    int i;
    printf("[D] sizeof argv is: %d\n", sizeof(argv) );
    printf("[D] sizeof int  is: %d\n", sizeof(int) );
    printf(
        "[D] sizeof argv / sizeof int is: %d\n",
        sizeof(argv) / sizeof(int)
    );

    for (i = 0; i < (sizeof(argv) / sizeof(int)); i++ ) {
        printf("[D] i is: %d\n", i );
        cout << argv[i] << endl;
    }

    if (cout.fail()) {
        printf("cout failed!\n");
    }

    cout << "Hello world" << endl;
}

现在测试:

aloism@azzgoat:~/sandbox/tuts$ g++ string02-d.cpp
aloism@azzgoat:~/sandbox/tuts$ ./a.out hello world
[D] sizeof argv is: 8
[D] sizeof int  is: 4
[D] sizeof argv / sizeof int is: 2
[D] i is: 0
./a.out
[D] i is: 1
hello
Hello world
aloism@azzgoat:~/sandbox/tuts$ ./a.out
[D] sizeof argv is: 8
[D] sizeof int  is: 4
[D] sizeof argv / sizeof int is: 2
[D] i is: 0
./a.out
[D] i is: 1
cout failed!
aloism@azzgoat:~/sandbox/tuts$ echo $?
0
aloism@azzgoat:~/sandbox/tuts$

为什么当argv中只有一个项目(argv [0],是“./a.out”)时,会跳过“Hello world”?我无法找到任何理由为什么会跳过这个,无论是argc还是argv!

操作系统是64位的Debian Squeeze(所以sizeof(int) == 4)。

更新:删除了#include噪音,添加了一些调试功能。

更新2:根据user315052的回答添加了一些调试。 (现在它表明他是对的。)

3 个答案:

答案 0 :(得分:5)

您的sizeof检查有问题,并且始终评估为2 [在64位]。因此,当您不为程序提供至少一个参数时,它会尝试从argv[1]的未映射内存进行打印,然后崩溃。

答案 1 :(得分:3)

编辑:,因为调用了未定义的行为,所以任何事情都可能发生。调整答案。

可能没有跳过“Hello World”。意识到你的for循环是不正确的。它可能没有出现的一个原因是你印有一些掩盖了信息外观的东西。要对此进行测试,请将输出重定向到将显示输出流的二进制内容的内容。

./a.out | xxd

另一个原因可能是输出被阻止,因为std::cout因尝试将NULL指针作为字符串打印而失败。要对此进行测试,请在循环中的print语句后检查std::cout.fail(),并在遇到消息时将消息定向到std::err

如Boann所示,该计划也可能会崩溃。但是,操作系统会为此提供诊断,并且您没有报告此类行为。

对于作为函数参数的数组,编译器将它们视为指针。这是从C继承的行为,其中数组通过“引用”传递,允许数组的名称衰减到其第一个元素的地址(除了少数例外,sizeof是其中之一)。因此,使用sizeof确定argv中的元素数量将无效。 C和C ++都提供了两种方法来确定何时到达argv向量的末尾。一个是argc,这是参数计数。第二个是argv的最后一个元素必须是NULL指针。

下次有真正的数组时,可以使用以下内容计算sizeof的元素数:

SomeThing array[] = { /* ... things ... */ };
size_t array_size = sizeof(array)/sizeof(array[0]);

这样,如果SomeThing发生更改,则仍可正确计算数组大小。

答案 2 :(得分:0)

我无法重现您的错误。在这两种情况下都会打印出“Hello World”。

kjp@vbox:~/Dev/ScratchDir$ ./a.out 
./a.out
Hello world
kjp@vbox:~/Dev/ScratchDir$ ./a.out Hello
./a.out
Hello world
kjp@vbox:~/Dev/ScratchDir$ 

你能检查一下是否有核心转储吗?