Каково значение '\n' в компиляторах C для старых Mac OS?
Фон:
В версиях Mac OS до версии 9 стандартное представление для текстовых файлов использовало символ ASCII CR (возврат каретки), десятичное значение 13, чтобы отметить конец строки.
Mac OS 10, в отличие от более ранних выпусков, похожа на UNIX и использует символ ASCII LF (перевод строки), значение десятичное 10, чтобы отметить конец строки.
Вопрос в том, каковы значения символьных констант '\n'
а также '\r'
в компиляторах C и C++ для Mac OS выпусков до OS X?
Есть (по крайней мере) два возможных подхода, которые можно было бы использовать:
- Лечить
'\n'
в качестве символа ASCII LF и преобразовывать его в и из CR при выводе и вводе из текстовых потоков (аналогично преобразованию между LF и CR-LF в системах Windows); или же - Лечить
'\n'
в качестве символа ASCII CR, который не требует преобразования на входе или выходе.
Со вторым подходом могут возникнуть некоторые проблемы. Одним из них является тот код, который предполагает '\n'
Это НЧ может потерпеть неудачу. (Такой код по сути своей непереносим.) Другое дело, что все еще должно быть отдельное значение для '\r'
и в системе на основе ASCII CR является единственным разумным значением. И стандарт С не позволяет '\n' == '\r'
(спасибо mafso за нахождение цитаты, пункт 5.2.2), так что для '\r'
,
Каков вывод этой программы на С, когда она скомпилирована и выполнена под Mac OS N, если N меньше 10?
#include <stdio.h>
int main(void) {
printf("'\\n' = %d\n", '\n');
printf("'\\r' = %d\n", '\r');
if ('\n' == '\r') {
printf("Hmm, this could be a problem\n");
}
}
Вопрос касается как C, так и C++. Я предполагаю, что ответ будет одинаковым для обоих.
Ответ также может варьироваться от одного компилятора C к другому, но я надеюсь, что разработчики компилятора будут поддерживать согласованность друг с другом.
Чтобы быть ясным, я не спрашиваю, какое представление старые версии Mac OS использовали для представления конца строки в текстовых файлах. У меня вопрос конкретно и только о значениях констант '\n'
а также '\r'
в исходном коде C или C++. Я знаю, что печать '\n'
(каким бы ни было его значение) в текстовый поток приводит к его преобразованию в системное представление конца строки (в данном случае, ASCII CR); такое поведение требуется стандартом C.
5 ответов
Значения символьных констант \r
а также \n
было то же самое в классической среде Mac OS, как и везде: \r
был CR был ASCII 13 (0x0d
); \n
был LF был ASCII 10 (0x0a
). Единственное, что отличалось на Classic Mac OS, было то, что \r
был использован в качестве "стандартной" строки, заканчивающейся в текстовых редакторах, так же, как \n
используется в системах UNIX, или \r\n
в системах DOS и Windows.
Вот скриншот простой тестовой программы, работающей в Metrowerks CodeWarrior на Mac OS 9, например:
Имейте в виду, что классические системы Mac OS не имели общесистемной стандартной библиотеки C! Функции как printf()
присутствовали только как часть специфичных для компилятора библиотек, таких как SIOUX для CodeWarrior, которые реализовали стандартный ввод / вывод на языке С, записывая выходные данные в окно с текстовым полем в нем. Таким образом, некоторые реализации стандартного файлового ввода-вывода могли выполнять автоматический перевод между \r
а также \n
, который может быть тем, о чем вы думаете. (Многие системы Windows делают подобные вещи для \r\n
если вы не пройдете "b"
флаг для fopen()
Например.) В Mac OS Toolbox не было ничего подобного.
Я сделал поиск и нашел эту страницу со старым обсуждением, где особенно можно найти следующее:
Реализация Metrowerks MacOS делает еще один шаг вперед, обращая вспять значение CR и LF в отношении экранирования '\r' и '\n' при вводе-выводе с участием файла, но не в каком-либо другом контексте. Это означает, что если вы откроете FILE или fstream в текстовом режиме, каждый '\r' будет выводиться там как LF, а также каждый '\n' выводится как CR, и то же самое верно для ввода - escape-to-ASCII-бинарные соответствия меняются местами. Однако они не обращаются в памяти, например, с помощью sprintf() в буфер или с помощью std::stringstream. Я нахожу это запутанным и, если не нестандартным, то, по крайней мере, хуже, чем другие реализации.
Оказывается, есть обходной путь с MSL - если вы открываете файл в двоичном режиме, то '\n' всегда == LF и '\r' всегда == CR. Это то, что я хотел, но, получая эту информацию, я также получил много оправдания от людей, что это был "стандартный" способ получить то, что я хотел, когда я чувствую, что это больше похоже на обход ошибки в их реализация. В конце концов, CR и LF являются 7-битными значениями ASCII, и я ожидаю, что смогу использовать их стандартным способом с файлом, открытым в текстовом режиме.
(Ответ проясняет, что это действительно не нарушение стандарта.)
Так что, очевидно, была по крайней мере одна реализация, которая использовала \n
а также \r
с обычными значениями ASCII, но перевели их в (недвоичный) вывод файла (просто обменяв их).
В старых компиляторах Mac роли \ r и \ n были изменены на противоположные: у нас было "\ n" == 13 и "\ r" == 10, а сегодня "\ n" == 10 и "\ r" == 13. Большое удовольствие на переходном этапе. Запишите '\ n' в файл со старым компилятором, прочитайте файл с новым компилятором и получите '\r' (конечно, оба раза у вас действительно было число 13).
У меня нет старого компилятора Mac, чтобы проверить, следуют ли они этому, но числовое значение '\n'
должен быть таким же, как символ новой строки ASCII (учитывая, что эти компиляторы использовали ASCII-совместимую кодировку в качестве кодировки выполнения, что, я полагаю, они сделали). '\r'
должно иметь то же числовое значение, что и возврат каретки ASCII.
Функции библиотеки или ОС, которые обрабатывают файлы в текстовом режиме, отвечают за преобразование числового значения '\n'
к тому, что ОС использует для завершения строк. Числовые значения этих символов во время выполнения полностью определяются набором символов выполнения.
Таким образом, поскольку мы по-прежнему выполняем ASCII-совместимые кодировки выполнения, числовые значения должны быть такими же, как и у классических компиляторов Mac.
Спецификация языка C:
5.2.2
...
2 Буквенные escape-последовательности, представляющие неграфические символы в наборе исполнительных символов, предназначены для выполнения действий на устройствах отображения следующим образом:
...
\ n (новая строка) Перемещает активную позицию в начальную позицию следующей строки.
\ r (возврат каретки) Перемещает активную позицию в начальную позицию текущей строки.
так \n
представляет соответствующий символ в этой кодировке символов... в ASCII это LF
голец