9 ms·
There are many reasons why C is not a low level language. Take the example: while `asm()` blocks are a common extension to C compilers, anything within the bloc
by II2II 27d ago
There are many reasons why C is not a low level language. Take the example: while `asm()` blocks are a common extension to C compilers, anything within the block is (a) compiler dependent and (b) architecture dependent. To choose an extreme counter example: you may as well claim that versions of BASIC with the POKE keyword are low level languages simply because you can POKE machine code directly into memory.
Yet one of the more interesting reasons, in my mind, is that C adds a tonne of abstractions. The roster of data types is one of those abstractions. Processors have a very weak notion of data types, and memory has absolutely no notion of memory types at all. For example: casting a `float` to an `int` has a very specific definition in C, and that definition involves altering the pattern of bits. While you can create a float and force the C compiler to regard that memory location as an int (via casting pointers), it isn't how the language is meant to be used (outside of rare cases).
If I recall correctly, some of the direct predecessors of C were typeless, which is closer to how the CPU and RAM treat data.
- weitendorf 27d agoThat's fair. C is very old and used for almost all hardware so I think while you can make the argument that "only clang and gcc extensions asm blocks available like that, and intrinsics are only available through vendor-specific headers" and be right, by that same logic literally nothing except binary machine code for hardware without any kind of microcode can be low-level, and even then it's probably always hardware dependent (because if it's not fully bijective to the actual hardware it's implemented on top of, the semantics leak). Practically speaking, we have a word for the kind of "abstractionless" model you're describing: machine code. I mean, even assembler is a bunch of abstractions about 'registers' and 'instructions' that are really just specific portions of the hardware or opcodes! So we either descend endlessly into pedantry arguing that cosmic rays and electron tunnelling represent inexcusable deviations from the overly abstracted semantics that hardware vendors expose in their products or maybe we draw the line somewhere else. You may not agree with mine, that "practical and simple interop with machine-level language impls across a high-level language interface is sufficiently close to the hardware as to be low level" but there has to be a limit somewhere between that and "technically the hardware's operating temperature is part of its logical semantics because if it exceeds a certain value for long enough it starts to degrade and yield incorrect results or terminate execution". I think eventually it just becomes unproductive nerd sniping, personally
- II2II 27d ago> Practically speaking, we have a word for the kind of "abstractionless" model you're describing: machine code. I mean, even assembler is a bunch of abstractions about 'registers' and 'instructions' that are really just specific portions of the hardware or opcodes! I understand what you are getting to here, and agree that we are getting into the domain of semantics. Yet it could be argued that (for the most part) there is a 1:1 mapping between assembly and the assembly processes is (mostly) reversible. Personally, this is where I would draw the line. > So we either descend endlessly into pedantry arguing that cosmic rays and ... I think I see where you're going, though I don't agree with the particular example. If you're saying that machine language is an abstraction in itself, that those sequences of 1's and 0's are a construct of electrical engineers to describe electrical pulses that control transistors in a chip, then I fully agree with you. And if you say that those electrical pulses and transistors are themselves abstractions of physical processes, then I fully agree with you. But I wouldn't really describe it as nerd sniping. These involve different disciplines that are examining the machine at fundamentally different levels.
- tremon 27d ago> Processors have a very weak notion of data types This is absolutely not true, unless you mean to say that processors should somehow support composite (aka C struct) data types as an instruction primitive. Processor operations have to be strongly typed, by definition. For example, these are the data types supported by operations in the modern x86 instruction set (ignoring vector extensions): - signed and unsigned integers of 8, 16, 32 and 64 bits - floating-point decimals of 32, 64 and 80 bits (and 128 via sse) - nul-terminated byte strings > For example: casting a `float` to an `int` has a very specific definition in C, and that definition involves altering the pattern of bits I don't understand this example. Casting a float to an int also has a very specific definition in IEEE-754 and is pretty much universally implemented as a hardware instruction. It has been in the x86 family since its inception: https://www.felixcloutier.com/x86/fisttp https://www.felixcloutier.com/x86/fisttp
- Pannoniae 27d agoI wholly agree, processors are strongly typed, even if there are holes like using integer instructions on floating-point values in XMM regs, very insightful comment:) btw a bit of nitpick: to be fair basically no one uses x87 anymore, it's https://www.felixcloutier.com/x86/cvttss2si https://www.felixcloutier.com/x86/cvttss2si and friends but yes :)
- uecker 27d agoFor "strongly typed" I would expect some type checking.
- TheOtherHobbes 27d agoTrue for IEE754 floating point operations, which are constrained to valid bit patterns. An operation on an invalid pattern - can happen with uninitialised memory - throws an exception. Otherwise, no.
- uecker 27d agoThis is still not type checking, it accepts whenever the bit pattern is a valid for floating point even when it originally was used as another type.
- rightbyte 27d ago> you may as well claim that versions of BASIC with the POKE keyword are low level languages simply because you can POKE machine code directly into memory. The contemporary Basic dialects of that time I could argue were low level languages. They were really thin. Like bcpl.