Где я могу найти странные, определенные правила синтаксиса C? - PullRequest
0 голосов
/ 08 мая 2018

Я сдам экзамен, и мой учитель задает странные правила синтаксиса Си. Как:

int q=5;  
for(q=-2;q=-5;q+=3) { //assignment in condition part??     
    printf("%d",q);      //prints -5  
    break;     
} 

Или

int d[][3][2]={4,5,6,7,8,9,10,11,12,13,14,15,16};     
int i=-1;     
int j;     
j=d[i++][++i][++i];   
printf("%d",j); //prints 4?? why j=d[0][0][0] ?

или

extern int a; 
int main() {     
    do {         
        do {              
            printf("%o",a); //prints 12         
        } while(!1);     
    } while(0);  
    return 0; 
} 
int a=10;

Я не мог найти правила какого-либо сайта или книги. Действительно абсурдно и необычно. Где я могу найти?

Ответы [ 3 ]

0 голосов
/ 08 мая 2018

Мне кажется, что ваш учитель задает вопросы, которые вызывают неопределенное поведение.

Если вы скажете ему, что это неправильно, вы прямо столкнетесь с ним.

Однако вы можете сделать следующее:

  1. Скомпилируйте код на разных платформах
  2. Скомпилируйте код с разными компиляторами
  3. Скомпилируйте код с разными версиями одного и того же компилятора
  4. Построить матрицу с результатами. Вы узнаете, что они отличаются
  5. Покажите результаты своему учителю и попросите его объяснить, почему это происходит

Таким образом, вы не говорите, что он неправ, вы просто показываете некоторые факты и показываете, что готовы учиться и работать.

Сделайте это за 1021 * задолго до экзамена, чтобы учитель мог посмотреть на него и подумать над своими вопросами, чтобы он мог вовремя изменить экзамен.

Я не мог найти правила какого-либо сайта или книги. Где я могу найти?

См. Где найти текущие стандартные документы C или C ++? . Если у вас есть хорошая библиотека в университете, у них должна быть копия.

0 голосов
/ 08 мая 2018

онлайн-версия стандарта языка C имеет то, что вам нужно (и именно на это я буду ссылаться в этом ответе); просто имейте в виду, что это определение языка , а не учебное пособие, и, как таковое, его может быть нелегко прочитать тому, кто еще не имеет большого опыта.

Сказав это, ваш учитель бросает вам несколько грязных мячей. Например:

j=d[i++][++i][++i];   

Это утверждение приводит к неопределенному поведению по нескольким причинам. Первые несколько абзацев раздела 6.5 связанного выше документа объясняют проблему, но в двух словах:

  • За исключением нескольких ситуаций, C не гарантирует оценку выражений слева направо; это также не гарантирует, что побочные эффекты будут применены сразу после оценки;

  • Попытка изменить значение объекта более одного раза между точками последовательности 1 или изменение, а затем попытка использования значения объекта без промежуточной точки последовательности приводит к неопределенному поведению .

По сути, не пишите ничего в форме:

x = x++;
x++ * x++;
a[i] = i++;
a[i++] = i;

C не гарантирует, что каждые ++i и i++ оцениваются слева направо, и не гарантирует, что побочный эффект каждой оценки применяется немедленно. Таким образом, результат j[i++][++i][++i] не является четко определенным, и результат не будет одинаковым для разных программ или даже для разных сборок одной и той же программы 2 .

И , кроме того, i++ соответствует значению current i; так ясно, что ваш учитель хотел, чтобы j[i++][++i][++i] оценил j[-1][1][2], что также приведет к неопределенному поведению, так как вы пытаетесь индексировать за пределами границ массива.

Вот почему я ненавижу, ненавижу, ненавижу это когда учителя бросают такой код в своих учеников - он не только бесполезно сбивает с толку, он не только поощряет плохую практику, но и чаще, чем нет это просто неправильно .

Что касается других вопросов:

for(q=-2;q=-5;q+=3) { //assignment in condition part?? 

См. Разделы 6.5.16 и 6.8.5.3. Короче говоря, выражение присваивания имеет значение (значение левого операнда после любых преобразований типов) и может появляться как часть управляющего выражения в цикле for. Пока результат присваивания не равен нулю (как в случае выше), цикл будет выполняться.

printf("%o",a); //prints 12         

См. Раздел 7.21.6.1. Спецификатор преобразования o указывает printf форматировать целочисленное значение как восьмеричное: 10<sub>10</sub> == 12<sub>8</sub>


Точка последовательности - это точка выполнения программы, в которой выражение полностью оценено и применены любые побочные эффекты. Точки последовательности появляются в конце операторов, между оценкой параметров функции и вызовом функции, после вычисления левого операнда операторов &&, || и ?: и нескольких других мест. См. Приложение C для полного списка.
Или даже разные прогоны одной и той же сборки, хотя на практике вы не увидите, как значения меняются от прогона к прогону, если вы не делаете что-то действительно странное.
0 голосов
/ 08 мая 2018

Что касается for(q=-2;q=-5;q+=3) {, все, что вам нужно сделать, это разбить это на составляющие. Сначала запускается q=-2, затем проверяется q=-5, и если это не 0 (а это не так, как выражение со значением -5), то тело цикла запускается один раз. Тогда break вызывает преждевременный выход из бесконечного цикла. Выражение тогда q+=3 никогда не достигается.

Поведение d[i++][++i][++i] равно undefined . Скажите своему учителю, тактично.

Формат "%o" обозначает восьмеричный вывод. a установлено в 10 в десятичном виде, что составляет 12 в восьмеричном. Ваш код был бы понятнее, если бы вы написали:

int a=012; // octal constant.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...