2016-11-03 6 views
3
void main() { 
    int i, j=6; 
    for(; i=j ; j-=2) 
     printf("%d",j); 
} 

Следуя шаблон регулярного, должно быть состояния после первой точки с запятой, но здесь это инициализация, так что это должно быть дано сообщением об ошибке. Как это даже допустимый формат?Почему эта часть кода не дает ошибку?

Но выход 642

+2

Это должно быть * выражение *, а присваивание - выражением. –

+1

Нет инициализации, есть задание. Btw 'void main' нестандартен. –

+1

Это в основном сокращение для '(i = j)! = 0', так как' 0' является 'false' – 4castle

ответ

3

Во-первых, позвольте мне исправить терминологии, i=j является назначение, не инициализации.

Сказанное, давайте проанализируем синтаксис цикла for.

for(пункт-1; выражение-2; выражение-3)заявление

Таким образом, выражение-2 должно быть "выражение".

Теперь, приходя к синтаксису для заявления, имеющего оператор присваивания

присваивания выражение:
условного выражения
унарного выражение присвоения Оператора присваивания выражения

Так, как указано в разделе §6.5.16, спецификация C11 операция присваивания также является выражением , которое идеально подходит для выражения -2 часть в for синтаксис цикла.

Что касается результате,

Выражение присваивания имеет значение левого операнда после присваивания,

так, i=j будет в основном присвоить значение j к i и то для проверки состояния будет использоваться значение i (т. е. ненулевое или ноль как TRUE или FALSE).

TL; DR Синтаксически с кодом не возникает никаких проблем, поэтому ваш компилятор не генерирует ошибок.


Кроме того, для принимающей среды, void main() должна быть int main(void) быть в соответствии со стандартом.

+0

Получил это. Спасибо :) –

+0

В отличие от этого, иногда ** main() ** содержит ** параметры ** [не пусто]. Что это такое? в деталях. –

+0

@NitishPrajapati, который ссылался на 'void main()'. который не обрабатывает аргументы командной строки, правильно? –

3

i=j также является выражением, значение которого является значением i после назначения. Таким образом, это может служить условием.

Вы бы нормально видеть этот тип сообразительности используется так:

if ((ptr = some_complex_function()) != NULL) 
{ 
    /* Use ptr */ 
} 

Если некоторые программисты любят складывать задание и проверить в одну строку кода. Насколько хорошо или плохо это для читаемости - вопрос мнения.

+0

О, ладно! Понял. Благодарю. –

+0

Btw является ptr указателем или просто переменной. Я предполагаю, что это просто переменная –

+1

@NitishPrajapati, я не уверен, что вы подразумеваете под «или». Указатель - это просто переменная, которая может содержать адрес определенного типа. – StoryTeller

1

Ваш код не содержит синтаксической ошибки, поэтому компилятор принимает его и генерирует код для создания 642.

Условие i=j интерпретируется как (i = j) != 0.

Чтобы предотвратить это и много подобных моделей ошибок, чтобы больше предупреждений компилятора и сделать их фатальными с:

gcc -Wall -W -Werror 

Если вы используете clang, используйте clang -Weverything -Werror

+0

Получил это.Спасибо. :) –

1

Это очень хороший вопрос.

Чтобы понять это, вам лучше знать, как коды C выполняются на компьютере: Сначала компилятор скомпилирует код C в код сборки, а затем коды сборки будут переведены в машинный код, который может работать в основной памяти непосредственно.

Что касается вашего кода:

void main() { 
    int i, j=6; 
    for(; i=j ; j-=2) 
     printf("%d",j); 
} 

Чтобы понять, почему результат 642, Мы хотим видеть свой код сборки.

Использование VS режим отладки, мы можем видеть:

enter image description here

Особенно посмотрите на это:

010217D0 mov   eax,dword ptr [j] 
010217D3 mov   dword ptr [i],eax 
010217D6 cmp   dword ptr [i],0 
010217DA je   main+4Fh (010217EFh) 

четыре линии сборки кода, соответствующего невозможному кода C "I = J" , это означает, что сначала переместите значение j для регистрации eax, затем переместите значение регистра eax на i (поскольку компьютер не может напрямую переместить значение j в i, он просто использует регистр eax в качестве моста), а затем сравните значение i с 0, если они равны, перейти к 010 217EFh, петля заканчивается; если нет, цикл продолжается.

Так что на самом деле это первое задание, затем сравнение, чтобы решить, закончен ли цикл; поскольку 6 отклоняется до 0, цикл, наконец, останавливается, я надеюсь, что это поможет вам понять, почему результат равен 642: D

+0

Спасибо. Да, это было полезно. Я понял концепцию –

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