Background:
In versions of Mac OS up to version 9, the standard representation for text files used an ASCII CR (carriage return) character, value decimal 13, to mark the end of a line.
Mac OS 10, unlike earlier releases, is UNIX-like, and uses the ASCII LF (line feed) character, value decimal 10, to mark the end of a line.
The question is, what are the values of the character constants '\n'
and '\r'
in C and C++ compilers for Mac OS releases prior to OS X?
There are (at least) two possible approaches that could have been taken:
- Treat
'\n'
as the ASCII LF character, and convert it to and from CR on output to and input from text streams (similar to the conversion between LF and CR-LF on Windows systems); or - Treat
'\n'
as the ASCII CR character, which requires no conversion on input or output.
There would be some potential problems with the second approach. One is that code that assumes '\n'
is LF could fail. (Such code is inherently non-portable anyway.) The other is that there still needs to be a distinct value for '\r'
, and on an ASCII-based system CR is the only sensible value. And the C standard doesn't permit '\n' == '\r'
(thanks to mafso for finding the citation, 5.2.2 paragraph 3), so some other value would have to be used for '\r'
.
What is the output of this C program when compiled and executed under Mac OS N, for N less than 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");
}
}
The question applies to both C and C++. I presume the answer would be the same for both.
The answer could also vary from one C compiler to another -- but I would hope that compiler implementers would have maintained consistency with each other.
To be clear, I am not asking what representation old releases of Mac OS used to represent end-of-line in text files. My question is specifically and only about the values of the constants '\n'
and '\r'
in C or C++ source code. I'm aware that printing '\n'
(whatever its value is) to a text stream causes it to be converted to the system's end-of-line representation (in this case, ASCII CR); that behavior is required by the C standard.
\n
and\r
have always been ASCII newline and ASCII carriage return -- 0x0A and 0x0D. But I gather that early (pre-*nix) versions of MacOs used more like a DOS/Windows line terminator --\r\n
in sequence. – Longobard\r
, not\r\n
, to mark end-of-line in files. But my question is about the constants in C or C++ code. – Garey'\n'
is tied to the term "newline", which does not appear in ASCII. UNIX has a convention of using LF (line feed) to mark the end of a line. – Gareyprintf("bla\n");
actually prints a carriage return, butprintf("%d\n", '\n');
don't give the ASCII value of the carriage return? – Xiaoximena\l
because you couldn't tell it from\1
--\n
was used instead, and the "newline" moniker was hung on it. – Longobardprintf("bla\n")
will print an ASCII CR character, because that's what the OS uses to mark end-of-line in text files. – Garey\r
as the line separator in text files. Since the C I/O library is responsible for transforming between filesystem and in-memory representation, I'd guess\n
s were serialized as\r
. – Vitia'\n'
='\r'
would be: Seems unchanged since C89… C11 5.2.2 p3: “Each of these escape sequences shall produce a unique implementation-defined value […]”. So, no, it's not conforming. But what about a character set using 0xd for'\n'
and 0xa for'\r'
? – Adrian'\r'
precisely in the same way as UNIX systems use'\n'
. There was never a DOS-like combination in use. Microsoft users always annoyed us with that extra character - the mac users with the line-feed, the unix users with the carriage-return... – Closetprintf
andscanf
family functions didn't just send and\n
and\r
that occurred in their first argument (as opposed to converted arguments) on unmodified. So that when I wrote K&R style utilities they produced files that worked on the machine they were run on and needed translation to work properly on a unix or dos machine. And as @Xiaoximena you can't test that with a numeric comparison of the values of the character literals or by printing the results after a%d
conversion. – Dugaidprintf
andscanf
work as if they repeatedly calledfputc
orfgetc
respectively.The following are all equivalent:
printf("\n"),
printf("%s", "\n"),
printf("%c", '\n')` andfputc('\n', stdout)
. Conversion of'\n'
(whatever it is) to and from the system's end-of-line marker happens for I/O to any text stream. That conversion is not what I'm asking about. I am specifically asking about the values of'\n'
and'\r'
-- andprintf("%d\n", '\n')
does answer that question. – Garey'\n'
and the runtime library's decision of which character to translate to an end-of-line representation do have to agree for the implementation to be conforming. (For UNIX-like systems that's trivial, since'\n'
is10
, i.e. LF, which is the system's end-of-line representation). – Garey\n
is still unique and different from memory than\r
. It's just that the classic Mac C I/O library is responsible for translating between\r
and\n
when writing to or reading from a file. – Vitia