9

It's my understanding that the reason that external identifiers in portable C programs had (still have?) to be unique in the first six characters is that six 6-bit characters¹ fill a 36-bit machine word on a target architecture, and that a single machine word was used to represent the identifier in object files.

I guess this applies to other languages too, if they use the same object-file format and linker.

Is my understanding correct? If so, which platform had such influence?


¹ Conveniently, and probably not coincidentally, 52 letters, 10 digits, underscore and null add up to 64 possibilities, neatly filling 6 bits.

3
  • 2
    Regarding the "had to be unique in the first six characters", I believe that is only "if you want to make sure your code is portable". I do not think it enforced and maybe not even diagnosed. But I don't write C these days. Feb 20, 2022 at 21:17
  • No, it doesn't require a diagnostic. I really should have included the word "portable" in there to begin with! Feb 21, 2022 at 7:32
  • 1
    IIRC, the C99 standard increased the minimum maximum length of an external identifier to 31 characters. Some linkers allow even greater lengths (e.g., 2047 chars in MSVC) for compatibility with mangled names in C++ (or similar languages with function overloading and potentially-complex class names).
    – dan04
    Feb 21, 2022 at 20:56

2 Answers 2

12

In the first edition of K&R, Appendix A paragraph 2.2 has a list of identifier length significance for the following platforms:

  • DEC PDP-11: 7 characters, 2 cases

  • Honeywell 6000: 6 characters, 1 case

  • IBM 360/370: 7 characters, 1 case

  • Interdata 8/32: 8 characters, 2 cases

The Honeywell 6000 thus seems to be the source of this limit. And indeed, it was a 36-bit machine. Though your math doesn't quite work out because it evidently wasn't case sensitive, so it only needed 26 letters, not 52.

8
  • 5
    Second Edition is not quite as informative in A.2.3: "Identifiers with external linkage ... implementations may make as few as the first six characters as significant, and may ignore case distinctions." I guess the background info was cut to make way for updates. At least it's consistent with the earlier edition! Feb 19, 2022 at 22:10
  • 4
    @TobySpeight: The reference manual in K&R I was specifically intended to document the implementations on those four particular systems. I expect K&R II, which was post-ANSI, tried to be more generic. Feb 19, 2022 at 22:17
  • 1
    @IanRingrose: I understand the "1 case" as "not case sensitive", i.e. only one case is allowed (or perhaps you can write mixed case in your code, but it is smashed to one case when compiled). So then Honeywell 6000 would include both those restrictions. Feb 20, 2022 at 17:25
  • 2
    DEC RAD50 used 5.333 bits per character: one 16-bit word = (ch1 * 050 * 050) + (ch2 * 050) + ch3. IBM had squoze format, which allowed 6 characters in 34 bits. Etc. Feb 20, 2022 at 23:53
  • 3
    I can confirm the Honeywell one is correct. The reason for this is quite simple. The linker stored each symbol in a 36bit machine word in 6 x 6bit BCD characters. That makes a symbol compare a single operation. On many older systems the symbol length had to be limited because you needed all the symbols in memory and memory was precious.
    – Alan Cox
    Feb 22, 2022 at 14:41
3

The six-character limit goes back to early FORTRAN systems which IIRC used a 36-bit word, and would use a single word of six 6-bit characters to hold each symbol. One of the intentions with C was that it be able to generate code that could be linked with code built using other languages. If a FORTRAN linker had a six-character limit and one wanted to use a C implementation to generate code for use with that linker, one would have to use symbols that could be accommodated by such a linker.

9
  • Yes. FORTRAN 77 and earlier versions had 6 as their standard "minimum". (You can see this, for example, here, at Oracle's online copy of the FORTRAN 77 standard.) IIRC longer identifiers were allowed but only the first 6 were significant, i.e., A12345X and A12345Y would have been considered the same identifier. A relevant issue is that because of the ubuiquity of FORTRAN, whether or not there was one for (early) Unix, most system linkers supported 6 as a minimum, and some as a maximum!
    – davidbak
    Feb 20, 2022 at 20:13
  • 2
    @another-dave - 6 characters was a relief after I left Vector Automation (Baltimore, MD) which based its CAD system on an HP1000 running some crap HP OS that that had 5 count'em: FIVE - character file names. No "extension" either, so really we used only FOUR characters with one for a file "type" (Pascal source, Assembly Source, Fortran Source, Object, etc.). Jeez that was painful. (I wrote the Pascal compiler for Vector Automation, that was very interesting and a bit of challenge for me then.)
    – davidbak
    Feb 21, 2022 at 0:54
  • 1
    @TobySpeight: I expect the one-word limitation goes back to the assemblers. I don't know, though, whether assemblers were designed around alphanumeric labels, or if they expected programmers to use numeric labels for things and keep a list of what labels had what meanings. Perhaps alphanumeric, but numeric could have some advantages if one were trying to maintain paper documentation, since one would have many more digits available to sort things into categories.
    – supercat
    Feb 21, 2022 at 15:37
  • 1
    @dan04: Or base 40 (decimal) or 50 (octal) to encode two 16-bit halves, which can actually be somewhat easier to parse since one can split off three bits of each character, leaving only two 5x5x5 triples to deal with.
    – supercat
    Feb 21, 2022 at 20:49
  • 1
    @dan04: Only if a padding character is included in the number of allowed characters, and/or at least one character is forbidden in the first position.
    – supercat
    Feb 21, 2022 at 21:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .