Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Please explain: Line skipped after for loop?

I'm trying to do my first baby steps with C++.

Can somebody explain why this does not work the way I'd expect?

#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;
}

Now the testing:

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$

Why when there is only one item in argv (argv[0], being "./a.out"), the "Hello world" is skipped? I can't find any reason at all why this would be skipped, no matter the argc or argv!

The OS is Debian Squeeze on 64-bit (so sizeof(int) == 4).

Update: Removed #include noise, added some debugging.

Update 2: Added some debugging based on user315052's answer. (Now it shows that he's right.)

like image 673
Alois Mahdal Avatar asked Dec 06 '25 13:12

Alois Mahdal


2 Answers

Your sizeof check is faulty and always evaluates to 2 [on 64-bit]. Consequently, when you don't give the program at least one argument, it tries to print from unmapped memory at argv[1], and crashes.

like image 80
Boann Avatar answered Dec 08 '25 02:12

Boann


Edit: since undefined behavior is invoked, anything can happen. Adjusting answer.

The "Hello World" is probably not being skipped. Realize your for loop is improper. One reason that it may not be appearing is that you have printed something that is covering up the appearance of the message. To test this, redirect the output into something that will reveal binary contents of the output stream.

./a.out | xxd

Another reason may be that the output is being blocked because std::cout suffered a failure from an attempt to print a NULL pointer as a string. To test for this, check for std::cout.fail() after the print statement in your loop, and direct a message to std::err if you encounter one.

The program may also crash, as indicated by Boann. However, the operating system would have provided a diagnostic to that effect, and you reported no such behavior.

For arrays that are function parameters, the compiler treats them as a pointer. This is a behavior inherited from C, where arrays are passed by "reference" by allowing the name of an array to decay to the address of its first element (with a few exceptions, sizeof being one of them). So, using sizeof to determine the number of elements in argv won't work. Both C and C++ provide two ways to determine when the end of the argv vector is reached. One is argc which is the argument count. The second is that the last element of argv must be a NULL pointer.

The next time you have a true array, you can calculate the number of elements with sizeof using the following:

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

This way, if SomeThing changes, the array size is still properly calculated.

like image 34
jxh Avatar answered Dec 08 '25 03:12

jxh



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!