3

我正在尝试使用 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 (so sizeof(int) == 4)。

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

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

4

3 回答 3

5

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

于 2012-06-17T15:38:25.707 回答
3

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

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

./a.out | xxd

另一个原因可能是输出被阻止,因为尝试将指针打印为字符串std::cout而失败。NULL要对此进行测试,请std::cout.fail()在循环中的 print 语句之后检查,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发生变化,仍然可以正确计算数组大小。

于 2012-06-17T15:39:06.737 回答
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$ 

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

于 2012-06-17T15:33:11.783 回答