There is 'printf'. It's just that printf (and the rest of the standard library) is technically as much a part of the C language as the language grammar itself, and C compilers are welcome to use innate knowledge of those functions for optimizations. The other place you typically see this is calls to functions like memcpy/memset being elided to inline vector ops or CISC copies, or on simpler systems, large manual zero…
The "no_std" idea is one that has washed up over and over again, over the last half-century. ISO Standards typically call it "freestanding". It has invariably failed to yield the promised benefits. It hangs around, anyway, cluttering up Standards. People waste endless hours proposing alterations to it for the next Standard edition, to be likewise ignored by implementers and informed users of whichever language. I don…
There is no 'printf'
151–158 of 158 posts
Re: There is no 'printf'
#152Earlier quoted context omitted.
> C compilers will typically have an escape hatch for envs like deeply embedded systems and kernels like gcc's -ffreestanding and -fno-builtin that says "but for real though, don't assume std lib functions exist or you know what they are based on the function's name". GCC requires standard library functions even on freestanding environments! It will still emit calls to those functions in certain circumstances. https:…
The requirements for memcpy, memmove, memset and memcmp stem from the fact that statements like "char arr[100] = {0};" or "struct somestruct some_a = some_b;" cause implicit memsets and memcpys, in cases where it can't be handled within less instructions. These functions are required by the freestanding part of the C standard, too, anyway.
Yeah, I know. Still, I expected GCC to generate code like this in freestanding environments. There is no standard library so the compiler should not implicitly emit any calls to standard library functions at all. That ought to have freed me to do whatever I want, including implementing those functions differently or with different names.
> These functions are required by the freestanding part of the C standard, too, anyway.
What? If I remember correctly, only a very small list of headers are required in freestanding environments and string.h was not among them.
Re: There is no 'printf'
#153Earlier quoted context omitted.
So the compiler actually can't optimize because of legacy errno cruft? That's hilarious...
The compiler respects the C standard by default. According to it, puts() is the same as a printf() in some conditions, but sqrt() is not the same as the instruction. If you don't like C, you can use a dialect of it by setting some flags: -fno-math-errno if you want to optimize sqrt anyway or -fno-builtin if you don't want the compiler to replace functions calls
> -fno-math-errno
That's interesting, didn't know about it.
Re: There is no 'printf'
#154Earlier quoted context omitted.
The standard leaves so much stuff undefined or implementation defined there's no way to fully understand what's going on anyway. The only mental model you can form is of the very limited non-existent abstract machine, anything else you have to guess or go to great pains to avoid. It just isn't very useful to think in those terms, so many intuitions just aren't possible. Turns the language into this huge minefield. I'…
It sounds like what you really want is a high-level portable assembler. Which, to be fair, is one of the niches that C has occupied... but I'm not convinced it's optimally designed for that in general, even leaving UB aside. But back in DOS days, there was something called Sphinx C--: https://bkhome.org/archive/goosee/cmm/c--doc.htm . A modern cross-arch reincarnation of that could be interesting.
Yeah.
More precisely, what I want is something that:
1. Gives me simple native code ELFs
2. Containing no symbols other than the functions I defined
3. That can interface directly with the Linux kernel with zero dependencies
If I bend C enough it turns into something resembling that. Freestanding C, a couple flags to fix the language and the compiler's inline assembly to fulfill the 3rd requirement. I agree that it's not perfect for the role but C compilers are way too important for me to simply disregard them and look for or invent a new language. I'd be giving up too much.
I wish the newer C standards took the time to define previously undefined behavior instead of adding even more cruft to the standard library. C11 is just the opposite of what I wanted.
Re: There is no 'printf'
#155Earlier quoted context omitted.
They're all system calls that are better served by using operating functions directly. I'm not sure how the compiler could possibly optimize those away though. Maybe the random function could become a very untrustworthy instruction?
Random number generation generally isn't handled by system calls. It's just computation. (Some languages do provide support for hardware [pseudo-]random number generation. C doesn't.) More generally, using system calls directly for things like getting the current time makes sense only if you don't care about portability. C can support both portable and non-portable code. Both are important. I get the impression that…
Definitely seems that way to me as well. Still, if I bend C enough it turns into something that's almost what I want. I just wish GCC had a couple more flags to control code generation in these surprising cases.
Re: There is no 'printf'
#156Earlier quoted context omitted.
It sounds like what you really want is a high-level portable assembler. Which, to be fair, is one of the niches that C has occupied... but I'm not convinced it's optimally designed for that in general, even leaving UB aside. But back in DOS days, there was something called Sphinx C--: https://bkhome.org/archive/goosee/cmm/c--doc.htm . A modern cross-arch reincarnation of that could be interesting.
> high-level portable assembler Yeah. More precisely, what I want is something that: 1. Gives me simple native code ELFs 2. Containing no symbols other than the functions I defined 3. That can interface directly with the Linux kernel with zero dependencies If I bend C enough it turns into something resembling that. Freestanding C, a couple flags to fix the language and the compiler's inline assembly to fulfill the 3r…
Then you have embedded, where the norm is either gcc (which loves to optimize away UB), or bespoke compilers produced by the hardware manufacturer that are usually full of weird bugs in any case.
Given that, is C really that important? I can see the ability to parse C headers as somewhat useful for the sake of interop, just so you could use all the libraries (and not just syscalls); but aside from that?
Re: There is no 'printf'
#157Earlier quoted context omitted.
Is is the opposite. The original C compiler produced instructions very closely to the higher level language. As such, it produces code based on what you tell it, no more, no less. If you don't tell it what value to return from a subroutine, it does not generate the code to. It is quite common to have a function that does not return a value. The case shown here is not a case of the compiler doing 'what it likes', but…
Is it undefined behavior?
Does the AX register exist in the caller? Yes.
Does it have a value? Yes.
Is its 'value' undefined. Yes.
Is there any undefined 'behaviour' of anything you told it to do? Not to me. Subtle maybe.
Re: There is no 'printf'
#158Earlier quoted context omitted.
Is it undefined behavior?
If you wrote the same thing in assembly language and, by convention, you return the value from a subroutine in the AX register. This function is not returning anything useful so you don't 'MOV AX,blah', yet your caller expected something in it, is it undefined? Does the AX register exist in the caller? Yes. Does it have a value? Yes. Is its 'value' undefined. Yes. Is there any undefined 'behaviour' of anything you to…