Live data from Hacker News

Weekend projects: getting silly with C

lcamtuf.substack.com

31–40 of 118 posts

Re: Weekend projects: getting silly with C

#31

> The above example will print the value of a, but it won’t be initialized to 123! It certainly could do though. In C, using an uninitialised variable does not mean "whatever that memory happened to have in it before" (although that is a potential result). Instead, it's undefined behaviour, so the compiler can do what it likes. For example, it could well unconditionally initialise that memory to 123. Alternatively, i…

UB can not travel back in time in C. Although it is true that it can affect previous instructions, but that code is reordered or transformed in complicated ways is true even without UB.

Re: Weekend projects: getting silly with C

#32
post #6

This can be used to implement coroutines in C. https://stackoverflow.com/questions/24202890/switch-based-co...

uIP (TCP/IP stack for tiny microcontrollers) is a another fun real-world example for these types of coroutines: https://github.com/adamdunkels/uip/blob/master/uip/lc-switch...

Re: Weekend projects: getting silly with C

#33
post #19

Earlier quoted context omitted.

While it's convenient technically to have unified memory and so it makes a lot of sense for your machine code, in fact the MMIO isn't just memory, and so to make this work anyway in the C abstract machine they invented the "volatile" qualifier. (I assume you weren't involved back then?) This should be a suite of intrinsics. It's the same mistake as "register" storage, a layer violation, the actual mechanics bleeding…

I wasn't involved back then, but I know the history. I thought you were talking about something more recent. But this is all opinions and terms such as "unholy mess" etc do not impress me. In my opinion "volatile" is just fine as is "register. Neither are layer violations nor a type system problem. That the exact semantics of a volatile access are implementation defined seem natural. How is this better with an intrin…

Sure, it's just an opinion. I think the consequences speak very well for themselves.

Re: Weekend projects: getting silly with C

#34
post #31

> The above example will print the value of a, but it won’t be initialized to 123! It certainly could do though. In C, using an uninitialised variable does not mean "whatever that memory happened to have in it before" (although that is a potential result). Instead, it's undefined behaviour, so the compiler can do what it likes. For example, it could well unconditionally initialise that memory to 123. Alternatively, i…

UB can not travel back in time in C. Although it is true that it can affect previous instructions, but that code is reordered or transformed in complicated ways is true even without UB.

The time-travelling UB interpretation was popularized by this blog post about 10 years ago [1].

I'm not enough of a specification lawyer to say that this is definitely true, but the reasoning and example given there seems sound to me.

[1] https://devblogs.microsoft.com/oldnewthing/20140627-00/?p=63...

Re: Weekend projects: getting silly with C

#35
post #31

> The above example will print the value of a, but it won’t be initialized to 123! It certainly could do though. In C, using an uninitialised variable does not mean "whatever that memory happened to have in it before" (although that is a potential result). Instead, it's undefined behaviour, so the compiler can do what it likes. For example, it could well unconditionally initialise that memory to 123. Alternatively, i…

UB can not travel back in time in C. Although it is true that it can affect previous instructions, but that code is reordered or transformed in complicated ways is true even without UB.

> but that code is reordered or transformed in complicated ways is true even without UB.

Without undefined behavior, the compiler emits code that has the behavior defined by the code —- the ordering may be altered, but not the behavior.

Re: Weekend projects: getting silly with C

#36

> The above example will print the value of a, but it won’t be initialized to 123! It certainly could do though. In C, using an uninitialised variable does not mean "whatever that memory happened to have in it before" (although that is a potential result). Instead, it's undefined behaviour, so the compiler can do what it likes. For example, it could well unconditionally initialise that memory to 123. Alternatively, i…

[deleted]

Re: Weekend projects: getting silly with C

#37

My undergrad was entirely in the C language and I’m very glad for it. Sometimes more modern languages can throw me for a loop, no pun intended, but the beauty (and horror) of C is that you are pretty close to the metal, it’s not very abstracted at all, and it allows you a lot of freedom (which is why it’s so foot gunny). I will never love anything as much as I love C, but C development jobs lie in really weird fields…

> I have seen C wizardry up close that I know I simply cannot do.

I have written C at least a few times per year for over 30 years. About ten years of that was OS development on Solaris and its derivatives.

Articles like this show crazy things you can do in C. I’ve never found the need to do things like this and have never seen them in the wild.

The places that wizardry is required are places like integer and buffer overflow, locking, overall structure of large codebases, build infrastructure, algorithms, etc. Many of these are concerns in most languages.

> auto reject C PR’s if they didn’t use the syntax if (1==x) rather than if (x==1)

When I was a student in the 90s advice like this would have been helpful. Compiler warnings and static analyzers are so much better now that tricks like this are not needed.

Re: Weekend projects: getting silly with C

#38
This reminds me of some silly C code I once wrote for fun, which counts down from 10 to 1:

    #include  // compile & run: gcc -Wall countdown.c -o countdown && ./countdown
    int n = 10; int main(int argc, char *argv[]) { printf("%d\n", n) && --n && main(n, NULL); }
Python version:

    import sys # run: python3 countdown.py 10
    def main(n:int): sys.stdout.write(f"{n}\n") and n-1 and main(n-1)
    main(int(sys.argv[1]))
Shell version:

    # run ./countdown.sh 10
    echo $1 && (($1-1)) && $0 $(($1-1))

Re: Weekend projects: getting silly with C

#39
post #35
post #31

Earlier quoted context omitted.

UB can not travel back in time in C. Although it is true that it can affect previous instructions, but that code is reordered or transformed in complicated ways is true even without UB.

> but that code is reordered or transformed in complicated ways is true even without UB. Without undefined behavior, the compiler emits code that has the behavior defined by the code —- the ordering may be altered, but not the behavior.

Yes, and with undefined behavior, the compiler has to emit code that has the behavior defined by the code up to the operation that has undefined behavior.

Re: Weekend projects: getting silly with C

#40
post #31

Earlier quoted context omitted.

UB can not travel back in time in C. Although it is true that it can affect previous instructions, but that code is reordered or transformed in complicated ways is true even without UB.

The time-travelling UB interpretation was popularized by this blog post about 10 years ago [1]. I'm not enough of a specification lawyer to say that this is definitely true, but the reasoning and example given there seems sound to me. [1] https://devblogs.microsoft.com/oldnewthing/20140627-00/?p=63...

Yes, random blog posts did a lot of damage here. Also broken compilers [1]. Note that blog post is correct about C++ but incorrectly assumes this is true for C as well.

[1]. https://developercommunity.visualstudio.com/t/Invalid-optimi...

Post reply on HN