Каково значение '\n' в компиляторах C для старой Mac OS?
Фон:
В версиях Mac OS до версии 9 стандартное представление текстовых файлов использовало символ ASCII CR (символ возврата каретки), значение decimal 13, чтобы отметить конец строки.
Mac OS 10, в отличие от предыдущих выпусков, является UNIX-подобным и использует символ ASCII LF (строка), значение десятичное 10, чтобы отметить конец строки.
Вопрос: каковы значения символьных констант '\n'
и '\r'
в компиляторах C и С++ для выпусков ОС Mac до OS X?
Есть (по крайней мере) два возможных подхода, которые можно было бы предпринять:
- Относитесь к
'\n'
как символ ASCII LF и преобразуйте его в и из CR на выходе и вводе из текстовых потоков (аналогично преобразованию между LF и CR-LF в системах Windows); или
- Лечить
'\n'
как символ ASCII CR, который не требует преобразования на входе или выходе.
Были бы некоторые потенциальные проблемы со вторым подходом. Один из них заключается в том, что код, который предполагает '\n'
, может быть неудачным. (В любом случае такой код по своей природе не переносится.) Другое дело, что для '\r'
все еще должно быть четкое значение, а в системе на основе ASCII CR - единственное разумное значение. И стандарт C не позволяет '\n' == '\r'
(благодаря mafso для поиска цитаты, 5.2.2 параграф 3), поэтому для '\r'
необходимо использовать другое значение.
Каков результат этой C-программы при компиляции и выполнении в 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 к другому, но я надеюсь, что разработчики компилятора будут поддерживать согласованность друг с другом.
Чтобы быть ясным, я не спрашиваю, какое представление старых выпусков Mac OS используется для представления конца строки в текстовых файлах. Мой вопрос конкретно и только о значениях констант '\n'
и '\r'
в исходном коде C или С++. Я знаю, что печать '\n'
(независимо от ее значения) в текстовый поток заставляет его преобразовываться в системное представление конца строки (в данном случае ASCII CR); это поведение требуется по стандарту C.
Ответы
Ответ 1
Значения констант символов \r
и \n
были такими же в средах Classic 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, например:
![Example program running in CodeWarrior]()
Имейте в виду, что в системах Classic Mac OS не было общедоступной стандартной библиотеки C! Такие функции, как printf()
, присутствовали только в составе специфичных для компилятора библиотек, таких как SIOUX для CodeWarrior, которые реализовали стандартный ввод-вывод C, путем записи вывода в окно с текстовым полем в нем. Таким образом, некоторые реализации стандартного ввода-вывода файлов могут выполнять автоматический перевод между \r
и \n
, что может быть тем, о чем вы думаете. (Многие системы Windows выполняют аналогичные действия для \r\n
, если вы не передаете флаг "b"
на fopen()
, например.) Однако, конечно, ничего не было в Mac OS Toolbox.
Ответ 2
Я выполнил поиск и нашел эту страницу со старым обсуждением, в котором, в частности, можно найти следующее:
Реализация Metrowerks MacOS идет еще дальше обращая значение CR и LF в отношении '\ r' и '\n' escape файлы в i/o с участием файла, но не в любом другом контексте. Это означает, что если вы откроете ФАЙЛ или fstream в текстовом режиме, каждый '\ r' будет выводиться там как LF, а также каждый "\n", выводимый как CR, и тот же верно для ввода - двоичные соответствия escape-to-ASCII-двоичные обращаются вспять. Однако они не меняются вспять, как в памяти, например. с sprintf() в буфер или с std:: stringstream. Я нахожу это запутанным и, если не нестандартным, по крайней мере хуже других реализаций.
Оказывается, есть обходное решение с MSL - если вы открываете файл в двоичном режиме, тогда '\n' always == LF и '\ r' always == CR. Это то, что я хотел, но в получении эта информация я также получил много оправданий от люди там, что это был "стандартный" способ получить что я хотел, когда я чувствую, что это больше похоже на обходной путь за ошибку в их реализации. В конце концов, CR и LF являются 7-разрядными значениями ASCII, и я ожидаю, что смогу использовать их их стандартным способом с файлом, открытым в текстовом режиме.
(Ответ дает понять, что это действительно не является нарушением стандарта.)
Таким образом, очевидно, что была хотя бы одна реализация, которая использовала \n
и \r
с обычными значениями ASCII, но переводила их в (не двоичный) вывод файла (просто обменивая их).
Ответ 3
Спецификация на языке C:
5.2.2
...
2 Алфавитные escape-последовательности, представляющие неграфические символы в наборе символов выполнения, предназначены для создания действий на устройствах отображения следующим образом:
...
\n (новая строка) Перемещение активной позиции в исходное положение следующей строки.
\ r (возврат каретки) Перемещение активной позиции в исходное положение текущей строки.
поэтому \n
представляет соответствующий char в этом символьном кодировании... в ASCII есть LF
char
Ответ 4
В старых компиляторах Mac роли \r и\n, где были обращены: у нас были '\n' == 13 и '\ r' == 10, а сегодня '\n' == 10 и '\ r '13. Очень весело во время переходного этапа. Напишите "\n" в файл со старым компилятором, прочитайте файл с новым компилятором и получите "\ r" (конечно, оба раза у вас на самом деле был номер 13).
Ответ 5
У меня нет старого компилятора Mac, чтобы проверить, следуют ли они этому, но числовое значение '\n'
должно совпадать с символом новой строки ASCII (учитывая, что эти компиляторы использовали ASCII-совместимую кодировку как исполняемую кодировку, которые, как я считаю, они сделали). '\r'
должно иметь то же числовое значение, что и возврат каретки ASCII.
Функции библиотеки или ОС, которые обрабатывают файлы текстового режима, отвечают за преобразование числового значения '\n'
в зависимости от того, что использует ОС для завершения строк. Числовые значения этих символов во время выполнения полностью определяются набором символов выполнения.
Таким образом, поскольку мы все еще поддерживаем ASCII-кодирование, числовые значения должны быть такими же, как у классических компиляторов Mac.