2012-06-17 12 views
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; 
} 

Теперь тестирование:

[email protected]:~/sandbox/tuts$ g++ string02-d.cpp 
[email protected]:~/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 
[email protected]:~/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! 
[email protected]:~/sandbox/tuts$ echo $? 
0 
[email protected]:~/sandbox/tuts$ 

Почему, когда есть только один пункт в ARGV (ARGV [0], будучи "./a.out"), то "Привет мир" пропускается ? Я не могу найти никакой причины, почему это было бы пропущено, независимо от argc или argv!

Операционная система: Debian Squeeze on 64-bit (так sizeof(int) == 4).

Обновление: Удалено #include шум, добавлена ​​некоторая отладка.

Обновление 2: Добавлена ​​некоторая отладка, основанная на ответе пользователя315052. (Теперь он показывает, что он прав.)

+2

Это должно быть 'for (i = 0; i Griwes

+3

Кстати, это не ** C++ **, это даже не допустимое объявление функции в ** C++ **! Это должно быть 'int main ...' –

+2

Вы не используете ни '', ни' '. В программе на C++ вы, вероятно, должны использовать '', когда вам нужны службы из заголовка C ''. –

ответ

3

Редактировать: так как вызывается неопределенное поведение, все может случиться. Настройка ответа.

«Hello World», вероятно, не пропускается. Реализовать цикл for не подходит. Одна из причин, по которой он не может появиться, заключается в том, что вы напечатали что-то, что скрывает внешний вид сообщения. Чтобы протестировать это, перенаправьте вывод на то, что покажет двоичное содержимое выходного потока.

./a.out | xxd 

Другой причиной может быть то, что выходной сигнал блокируется из-за std::cout потерпели неудачу из попытки напечатать NULL указатель в виде строки. Чтобы проверить это, проверьте для 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 изменения, размер массива до сих пор должным образом рассчитывается.

+0

Или, еще лучше, './a.out | hd'. – Griwes

+0

'xxd' или' hd' не показывали «Hello world» в любом месте:/ –

+0

@Griwes: Спасибо за ввод, у меня нет 'hd' в моей системе, но я думаю, что труба лучше. Сделано редактирование. С уважением – jxh

0

Я не могу воспроизвести вашу ошибку. «Hello World» печатается в обоих случаях для меня.

[email protected]:~/Dev/ScratchDir$ ./a.out 
./a.out 
Hello world 
[email protected]:~/Dev/ScratchDir$ ./a.out Hello 
./a.out 
Hello world 
[email protected]:~/Dev/ScratchDir$ 

Возможно, вы можете проверить, есть ли свалка ядра?

+0

Нет дампа ядра, а '$?' Равно нулю. –

+0

Хорошо, возможно, это печать какого-то барахла, который возвращается на ваш Hello World. Можете ли вы сделать. ./a.out | hd' like @Griwes говорит – kjp

+3

«Я не могу воспроизвести вашу ошибку». kjp соответствует неопределенному поведению, неопределенное поведение соответствует kjp. –

5

Ошибка вашего размера проверена и всегда оценивается в 2 [на 64-разрядной версии]. Следовательно, когда вы не даете программе хотя бы один аргумент, она пытается распечатать из немаркированной памяти по argv[1] и сбой.