【问题标题】:What is the value of '\n' under C compilers for old Mac OS?旧 Mac OS 的 C 编译器下 '\n' 的值是什么?
【发布时间】:2014-07-31 18:04:26
【问题描述】:

背景:

在最高版本 9 的 Mac OS 版本中,文本文件的标准表示使用 ASCII CR(回车)字符(十进制值 13)来标记行尾。

Mac OS 10 与早期版本不同,它类似于 UNIX,并使用 ASCII LF(换行)字符(十进制值 10)来标记行尾。

问题是,在 OS X 之前的 Mac OS 版本的 C 和 C++ 编译器中字符常量 '\n''\r' 的值是什么?

有(至少)两种可能的方法可以采取:

  1. '\n'视为ASCII LF字符,并在文本流的输出和输入中将其与CR转换(类似于Windows系统上的LF和CR-LF之间的转换);或
  2. '\n' 视为ASCII CR 字符,不需要对输入或输出进行转换。

第二种方法会有一些潜在的问题。一是假设'\n' 是LF 的代码可能会失败。 (无论如何,这样的代码本质上是不可移植的。)另一个是'\r' 仍然需要一个不同的值,并且在基于 ASCII 的系统上,CR 是唯一合理的值。并且 C 标准不允许 '\n' == '\r'(感谢 mafso 找到引用,5.2.2 第 3 段),因此必须将一些 other 值用于 '\r'

这个C程序在Mac OS下编译执行NN小于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 用什么表示法来表示文本文件中的行尾 。我的问题是专门针对 C 或 C++ 源代码中的常量 '\n''\r' 的值。我知道将'\n'(无论它的值是什么)打印到文本流会导致它被转换为系统的行尾表示(在本例中为ASCII CR);这种行为是 C 标准所要求的。

【问题讨论】:

  • 添加了 mac-classic 标签...
  • 现在启动我的旧 iMac...我很快就会有答案。 (Mac OS 8.6)
  • Classic Mac 使用\r 作为文本文件中的行分隔符。由于 C I/O 库负责文件系统和内存表示之间的转换,我猜\ns 被序列化为\r
  • 为了解决如何符合标准 '\n' = '\r':自 C89…C11 5.2.2 p3 以来似乎没有变化:“这些转义序列中的每一个都应产生唯一的实现定义的值 [… ]”。所以,不,它不符合要求。但是对于 '\n' 使用 0xd 和 '\r' 使用 0xa 的字符集呢?
  • @HotLicks 在我的记忆中,旧 Mac 使用 '\r' 的方式与 UNIX 系统使用 '\n' 的方式完全相同。从来没有使用过类似 DOS 的组合。微软用户总是用那个额外的字符惹恼我们——mac用户用换行符,unix用户用回车符......

标签: c++ c mac-classic


【解决方案1】:

字符常量 \r\n 的值在经典 Mac OS 环境中与在其他任何地方完全相同:\r 是 CR 是 ASCII 13 (0x0d); \n 是 LF 是 ASCII 10 (0x0a)。在经典 Mac OS 上唯一不同的是 \r 用作文本编辑器中的“标准”行结尾,就像在 UNIX 系统上使用 \n 或在 DOS 和 Windows 系统上使用 \r\n 一样。

这是一个在 Mac OS 9 上的 Metrowerks CodeWarrior 中运行的简单测试程序的屏幕截图,例如:

请记住,经典 Mac OS 系统没有系统范围的标准 C 库! printf() 之类的函数仅作为特定于编译器的库的一部分存在,例如 CodeWarrior 的 SIOUX,它通过将输出写入带有文本字段的窗口来实现 C 标准 I/O。因此,标准文件 I/O 的某些实现可能已经在 \r\n 之间执行了一些自动转换,这可能是您所想的。 (例如,如果您不将 "b" 标志传递给 fopen(),许多 Windows 系统对 \r\n 执行类似的操作。)不过,Mac OS 工具箱中肯定没有类似的东西。

【讨论】:

  • 你有这个参考吗?顺便说一句,任何符合要求的托管 C 实现都必须包含完整的标准库,包括 printf;操作系统不需要提供这样的实现。
  • 平均stdout(在文本模式下)在fputc('\n') [因文本模式翻译] 和fputc('\r') 都发出了13?
  • @duskwuff:但是 stdio 可以打开文件(fopen)并且那里写入了哪些字节是可以测试的。
  • 这个答案是正确的。然而,还有一个标准库的变体,可以解释以文本模式打开的文件。也就是说,如果文件包含一个 \r (13),当你在文本模式下阅读它时,你会得到一个 \n (10)。在输出时,您将写入一个 \r (13),它实际上会作为 \n (10) 写入磁盘。
  • @LưuVĩnhPhúc:Apple 的MPW 对开发人员来说是一个极好的环境——你可以像 shell(或终端)一样使用它,但每个“会话”也是一个可编辑的文本文档——我想念它。
【解决方案2】:

我进行了搜索,发现 this page 有一个旧的讨论,特别是可以找到以下内容:

Metrowerks MacOS 实现更进了一步 反转 CR 和 LF 的重要性 '\r' 和 '\n' 在涉及文件的 i/o 中转义,但不是 在任何其他情况下。这意味着如果您打开 FILE 或 fstream 在文本模式下,每个 '\r' 将在那里输出为 一个 LF 以及每个 '\n' 都作为 CR 输出,并且相同 输入为真 - 转义到 ASCII 二进制对应 被逆转。但是在记忆中它们并没有反转,例如 使用 sprintf() 到缓冲区或使用 std::stringstream。 我觉得这很混乱,如果不是非标准的话,至少 比其他实现更糟糕。

事实证明,MSL 有一个解决方法 - 如果您打开 二进制模式下的文件然后 '\n' 总是 == LF 和 '\r' 总是 == CR。这就是我想要的,但在得到 这个信息我也得到了很多理由 那边的人说这是获得的“标准”方式 我想要什么,当我觉得这更像是一种解决方法 对于他们的实现中的错误。毕竟 CR 和 LF 是 7 位 ASCII 值,我希望能够使用 以文本模式打开文件的标准方式。

(答案清楚地表明这确实违反标准。)

显然,至少有一个实现使用\n\r和通常的ASCII值,但将它们转换为(非二进制)文件输出(通过交换它们) .

【讨论】:

  • 假设'\n' == 10 (ASCII LF),将'\n' 写入文本流必须将其转换为 CR,因为这是系统的最终结果-线标记。此外,我认为将'\r' 转换为 LF 是有道理的,并且以二进制模式打开文件会抑制翻译。 (这都是标准 C 的东西)。所以在 Metroworks 下,我的问题中程序的输出是'\n' = 10\r = 13。就我的问题而言,这与黄昏的回答是一致的。
  • @KeithThompson 我用来说明我的答案的编译器 Metrowerks CodeWarrior!
【解决方案3】:

在较旧的 Mac 编译器上,\r 和 \n 的角色颠倒了:我们有 '\n' == 13 和 '\r' == 10,而今天 '\n' == 10 和 '\r ' == 13. 在过渡阶段非常有趣。使用旧编译器将 '\n' 写入文件,使用新编译器读取文件,并获得 '\r' (当然,这两次你实际上都有一个数字 13)。

【讨论】:

  • 我认为你倒退了; '\n' == 10'\r' == 13 将是现代版本。
  • 如果 I/O 函数进行转换(如在 Windows 中将\n 转换为\r\n),也会出现读取和写入文件的问题。只是为了确定:'\n' == 13 在这样的系统上是否评估为 1?
  • 这不是真的。 \r 总是 CR 是 ASCII 13; \n 总是 LF 是 ASCII 10。经典 Mac OS 只是使用 \r 作为标准行结尾而不是 \n,就像 DOS/Windows 使用 \r\n 序列一样。
  • @duskwuff:但我们有一个断言,在 Classic Mac OS 下,'\n' == 13。我认为我们需要在我的问题中查看程序的实际输出来解决这个问题。
  • @duskwuff 提供了屏幕截图,表明'\n' == 10'\r == 13;大概'\n' 将在输出时转换为 CR。您的回答似乎暗示 '\n''\r' 文字的值被颠倒了,这与截图的证据不一致。会不会是不同的 C 编译表现不同?
【解决方案4】:

C 语言规范:

5.2.2
...
2 表示执行字符集中非图形字符的字母转义序列旨在在显示设备上产生如下操作:
...
\n(新行)将活动位置移动到下一行的初始位置。
\r (回车) 将活动位置移动到当前行的初始位置。

所以\n 表示该字符编码中的适当字符...在ASCII 中是LF 字符

【讨论】:

  • 我不相信这能回答这个问题。该部分还描述了\f\v预期 行为;很少有系统能像描述的那样运行。
  • @KeithThompson 我正在寻找一个支持 char 值交换的文档......由编译器......我相信他们是这样工作的,我有一些旧的经典程序似乎可以强制执行这个想法,但我现在无法运行它们。
  • @GradyPlayer:如果你有一些那个时期的可执行文件,你可以用十六进制查看器检查你的字符串。我很确定现代人不会再默默地将\r 翻译回\n ;-)
  • 我认为这确实回答了这个问题......我们并没有真正在 Mac 上运行可移植的 C 程序,它们最初是用 Pascal 编写的,后来是用 C/C++ 编写的,但我们甚至没有有一个控制台...所以换行符的概念基本上只是在本机控件和文本文件中,我记得每个 mac 程序都将 \n、\r 和 \r\n 作为换行符... printf 甚至打印?
  • @GradyPlayer:问题是关于 '\n''\r' 字符常量的实际值,而不是关于 I/O 的行为方式。黄昏已经能够编译和运行我的问题中的可移植 C 程序并生成屏幕截图。
【解决方案5】:

我没有旧的 Mac 编译器来检查它们是否遵循这个,但 '\n' 的数值应该与 ASCII 换行符相同(假设那些编译器使用 ASCII 兼容编码作为执行编码,我相信他们做到了)。 '\r' 应该与 ASCII 回车具有相同的数值。

处理写入文本模式文件的库或操作系统函数负责将'\n' 的数值转换为操作系统用来终止行的任何值。这些字符在运行时的数值完全由执行字符集决定。

因此,由于我们仍然是 ASCII 兼容的执行编码,因此数值应该与经典 Mac 编译器相同。

【讨论】:

  • ASCII 并不意味着 LF 字符是“换行符”;事实上 ASCII 没有换行符。旧 Mac OS 的符合标准的 C 实现可以有 '\n' == 13 &amp;&amp; '\r' == 10(输入或输出不需要转换)它可以有 '\n' == 10 &amp;&amp; '\r' == 13(在文本输出上将 LF 转换为 CR,将 CR 转换为 LF关于文本输入。C 和 ASCII 标准本身并不能回答我的问题,即经典 Mac OS 的 C 和 C++ 编译器的作者做出了两个(或多个)有效选择中的哪一个。
  • 这将是一个符合要求的实现,但这意味着编码不是 ascii。 ascii 字符不需要命名为“换行符”来表示相同的意思。这个问题完全归结为“经典 Mac 计算机使用的执行编码是什么。”
  • 怎么样? ASCII 标准中的什么暗示 LF 是用于换行符的正确字符?
  • 嗯,我确信我可以找到一个合理的,但我找不到 ANSI 文档 X3.4-1986 (R1997) 的副本。 “换行”肯定会导致当前行的打印结束。
  • 现有的 C 实现在多大程度上遵循 ASCII 标准?例如,将换页或垂直选项卡打印到终端(例如 xterm 窗口)通常什么都不做。我不认为我们可以使用 ASCII 标准的要求来推断 C 编译器如何实现 '\n' 字符常量。
猜你喜欢
  • 1970-01-01
  • 2011-02-20
  • 2022-01-22
  • 1970-01-01
  • 2013-09-26
  • 2014-02-18
  • 1970-01-01
  • 2017-03-22
  • 1970-01-01
相关资源
最近更新 更多