2017-01-18 7 views
2

Я начал кодирование C в vim, и у меня есть некоторые проблемы.Соединительные линии в C [Незначительный выход несовместим с документацией]

обратной косой предназначен присоединиться к линии, но когда я пытаюсь написать:

ret\ 
urn 0; 

Я получаю

return 
    0; 

и когда я добавить пробелы до urn; его остаться, как, что без объединения.

ret\ 
    urn 0; 

остается таким.

почему во втором случае я не получаю return 0; но

ret 
    urn 0; 

код: enter image description here

CPP выход:

enter image description here

Команда:

gcc -E -Wall -Wextra -Wimplicit -pedantic -std=c99 main.c -o output.i 

GCC 5.4, Вим 7,4

+0

В чем вопрос? –

+0

Где код, воспроизводивший вашу проблему? –

+0

нет необходимости в коде. Я не забочусь о выполнении кода, я говорю о фазе препроцессора !!! – Sabrina

ответ

1

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

Что видит компилятор, это что-то вроде ret urn;. Который недействителен C, так как это два токена, которые, вероятно, не были определены ранее, и не являются допустимым выражением.

Ключевые слова должны быть записаны как один токен без пробелов.

Теперь, когда вы делаете:

ret\ 
urn; 

обратной косой с последующим переводом строки удаляется на ранних этапах перевода, и последующая строка добавляется. Если строка не имеет пробелов в начале, результатом является действительный токен, который компилятор понимает как ключевое слово return.


Короткий рассказ, вы, кажется, спрашиваете о specific behavior for GCC. Это похоже на ошибку компилятора. Поскольку clang does the expected thing (хотя количество строк остается тем же):

clang -E -Wall -Wextra -Wimplicit -pedantic -std=c99 -x c main.cpp 
# 1 "main.cpp" 
# 1 "<built-in>" 1 
# 1 "<built-in>" 3 
# 316 "<built-in>" 3 
# 1 "<command line>" 1 
# 1 "<built-in>" 2 
# 1 "main.cpp" 2 
int main(void) { 
    ret urn 0; 

} 

Это не кажется важным, однако, так как в данном случае код будет недействительным в любом случае.

+0

проблема не в том, что я получаю две отдельные строки. Ваш ответ - это нормальное поведение. Вот почему я задаю вопрос. – Sabrina

+0

@ Сабрина - Что значит «Я получаю две отдельные строки» * означает? Откуда вы должны это получить? Вы пишете свой код. – StoryTeller

+0

@ Сабрина - Спасибо, что разработали свой вопрос. См. Мое редактирование, пожалуйста. – StoryTeller

0

Поведение препроцессора C на \, за которым следует новая строка, состоит в том, чтобы удалить оба байта из ввода. Это делается на очень ранней стадии синтаксического анализа.Однако препроцессор сохраняет исходный номер строки для каждого маркера, который он видит, и пытается вывести токены в отдельных строках, чтобы компилятор выдавал правильную диагностику для последующих этапов компиляции.

Для ввода:

ret\ 
urn 1; 

может производить:

#line 1 "myfile.c" 
return 
#line 2 "myfile.c" 
1; 

Что это может сократить срок, как

return 
1; 

Обратите внимание, что вы можете разделить любую входную линию в любом положении сбежавшая строка новой строки:

#inclu\ 
de <st\ 
dio.h>\ 

"Hello word\\ 
n" 

for (i = 0; i < n; i+\ 
+) 

ret\ 
\ 
\ 
urn; 

\ 
r\ 
et\ 
urn\ 
123;\ 
3

-E вывод официально не указан в стандарте. Это инженерный компромисс между несколькими различными ограничениями дизайна, из которых соответствующие два являются:

  • пробелы должны быть вставлены или удалены по мере необходимости так, что «собственно компилятор» (представьте себе подачу -E выход обратно в gcc -fpreprocessed - который что -save-temps делает) видит ту же последовательность pp-tokens, что это обычно (без -E). (См. Раздел 6.4 раздела 6.4 для определения pp-токена.)
  • в максимально возможной степени, токены должны отображаться в той же строке и позиции столбца, что и в исходном исходном коде, чтобы сообщения об ошибках и информация об отладке насколько это возможно.

Вот как это относится к вашим примерам:

ret\ 
urn 0; 

обратной косой перевод строки объединяет ret и urn в один рр-токенов, которые поэтому должны появиться все вместе на одной линии на выходе. Тем не менее, 0 и ; должны оставаться в исходной строке и столбце, чтобы диагностика была точной. Таким образом, вы получите

return 
    0; 

с пробелами вставленных держать 0 в своей первоначальной колонке.

ret\ 
    urn 0; 

Здесь обратная косая-перевод строки сразу следует пробел, так ret и urn сделать не должны быть объединены, так что, опять же, диагностика наиболее точным, если все остается там, где оно первоначально было, и выход

ret 
    urn 0; 

, который выглядит как обратная косая черта-новая линия, не имела никакого эффекта.

Вы можете найти вывод gcc -E -P менее удивительным. -P сообщает препроцессору не беспокоить попытку сохранить позицию маркера (а также отключает все эти строки, начинающиеся с вывода #). Ваши примеры производят return 0; и ret urn 0;, причем все в одной строке, в режиме -P.

Наконец, совет: каждый, кто когда-либо читать ваш код (и который включает в себя шесть месяцев спустя) будет признателен, если вы не никогда разделить маркер в середине с обратной косой черты, символ новой строки, очень за исключением длинными строковыми литералами. Это устаревшая ошибка, которая не была бы включена в язык, если бы она была разработана с нуля сегодня.

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