2010-04-10 7 views
2

Эта часть моего кода работает отлично:Нужна помощь понимание странного поведения C

#include <stdio.h> 

int main(){ 
    //char somestring[3] = "abc"; 
    int i, j; 
    int count = 5; 

    for((i=0) && (j=0); count > 0; i++ && j++){ 
     printf("i = %d and j = %d\n", i, j); 
     count--; 
    } 

    return 0; 
} 

Выход, как и ожидалось:

i : 0 and j : 0 
i : 1 and j : 1 
i : 2 and j : 2 
i : 3 and j : 3 
i : 4 and j : 4 

Вещи становятся странно, когда я раскомментировать декларацию символьную строку на первая строка тела функции.

#include <stdio.h> 

int main(){ 
    char somestring[3] = "abc"; 
    ... 
} 

Выход:

i : 0 and j : 4195392 
i : 1 and j : 4195393 
i : 2 and j : 4195394 
i : 3 and j : 4195395 
i : 4 and j : 4195396 

Что логика за этим? Я использую gcc 4.4.1 на Ubuntu 9.10.

+4

Что такое i = 0 && j = 0? не должно быть i = 0, j = 0? аналогично для i ++ && j ++ –

+5

Строка '' abc "' занимает 4 байта, а не 3. Один для терминатора '\ 0' в конце. Оставьте размер из массива и дайте компилятору заполнить его. – GManNickG

+0

@GMan: Очень приятно, никогда не видел этого. @Mahesh: Что касается странного синтаксиса, я просто хотел немного проиграть с булевым, и, поскольку у меня появился некоторый фальшивый положительный результат из моего первого примера, я не обращал внимания на то, что j не инициализируется. Спасибо всем. –

ответ

18

j никогда не инициализируется из-за short-circuiting behaviour от &&. Поскольку (i=0) оценивает значение false, (j=0) никогда не запускается, и, следовательно, j получает случайное значение. В первом примере это просто нулевое значение.

Вы должны сказать i=0, j=0, чтобы достичь желаемого.

i++ && j++ имеет такую ​​же проблему; он должен быть i++, j++.

Кроме того, это:

char somestring[3] = "abc"; 

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

char *somestring = "abc"; 

вместо этого.

+0

Последняя строка будет лучше написана как «char somestring [] =« abc »;» в том, что она по-прежнему является массивом и модифицируема, тогда как вы превратили «somestring» в указатель на немодифицируемую область. Это зависит от того, как используется переменная. На этапе инициализации вы можете написать «i = j = 0'». Хороший ответ. –

+0

Ваш 'somestring' - это указатель, в то время как исходный' somestring' (mike's) был массивом. Лучшим решением, которое не нарушало бы существующий код, было определение 'char somestring [] =" abc ";', так что 'sizeof' все равно возвращал бы значимое значение и т. Д. – conio

+0

@Jonathan, @conio: Хорошая точка, но Я думаю, маловероятно, что Майк собирался полагаться на то, что эта строка можно записать. Я бы ошибался на стороне помещения строк в память только для записи, пока не узнал, что мне нужно написать им. В любом случае, ответ исправлен. – RichieHindle

1

for((i=0) && (j=0)... кажется уже некорректным.
i=0 уже имеет значение 0, поэтому оценка j=0 не требуется, поэтому его пропускают.

(i++) && (j++), по-видимому, неверен и для самой первой итерации по той же причине.

2

Если вы используете & &, то только первый аргумент получает оценку, если он неверен. я = 0 ложно, поэтому J не получает установлен в 0. Вы должны использовать оператор Komma:

for((i=0) , (j=0); count > 0; i++, j++){ [...] 
0

Вы используете (i==0) && (j==0) инициализацию обе переменные в цикле.

Однако свойство & & состоит в том, что если первый операнд оценивает FALSE (то есть 0), второй операнд никогда не выполняется. Итак, поскольку i равно 0, j остается неинициализированным. В вашем первом прогоне вы были просто повезло, что оно имело значение 0.

0

Ваши переменные i & j не инициализированы. Что вы подразумеваете: (i=0) && (j=0)? Компилятор сделает ярлык, и только назначить i=0 j остается неинициализированным с описанным эффектом.

Смежные вопросы