Live data from Hacker News

Lesser known tricks, quirks and features of C

blog.joren.ga

101–110 of 189 posts

Re: Lesser known tricks, quirks and features of C

#101

Here's another one. Handy "syntax" that makes it possible to iterate an unsigned type from N-1 to 0. (Normally this is tricky.) for (unsigned int i = N; i --> 0;) printf("%d\n", i); This --> construction also works in JavaScript and so on.

how would you iterate over every possible value of a unsigned int?

The unary complement operator should get you there:

  unsigned int x = 0;
  const unsigned int max = ~x;

  while (x 
Or,

  #include 

  const unsigned int max = UINT_MAX;

Re: Lesser known tricks, quirks and features of C

#102
post #6

Fun fact about %n: Mazda cars used to have a bug where they used printf(str) instead of printf("%s", str) and their media system would crash if you tried to play the "99% Invisible" podcast in them. All because the "% In" was parsed as a "%n" with some extra modifiers. https://99percentinvisible.org/episode/the-roman-mars-mazda-...

Fun fact about %n: The %n functionality also makes printf accidentally Turing-complete even with a well-formed set of arguments. A game of tic-tac-toe written in the format string is a winner of the 27th IOCCC. - sez wiki. A not so fun fact: Because the %n format is inherently insecure, it's disabled by default. - MSVC reference.

>The %n functionality also makes printf accidentally Turing-complete

No it doesn't. Printf has no way to loop so it's not Turing complete. Even if you did what the IOCCC entry did with putting it into a loop it still wouldn't be Turing complete as it would not have an infinite memory.

Re: Lesser known tricks, quirks and features of C

#103

Earlier quoted context omitted.

The simplest languages tend to be the most difficult. Brainfuck, Binary Lambda Calculus, Unlambda, and other "Turing tarpits" are all extremely difficult to use for anything even mildly complex.

Forth. It’s easy for a small cute script. But quickly becomes a PITA.

Stack machines look cool until you realize you could save all the stack mumbling by using registers. At this point, you could try to make a full VM instead.

Re: Lesser known tricks, quirks and features of C

#104
I wish there was a language "between" assembly and C: basically assembly with some quality-of-life improvements.

Shortcuts to reduce redundant chores (like those multiple instructions to load one 64-bit number into an ARM register) but minimal "magic" or unintended consequences as in C. Things like maybe a function call syntax like:

CALL someFunc(R1: thingForRegister1, @R7: pushR7ThenPopOnReturn, R42: [memoryAddressForR42])

and the function might be defined as:

someFunc(R1 as localNameForR1, R7 as oneMoreThing, R42? as optionalArgument)

and so on. (but anyone could come up with better ideas than me)

Re: Lesser known tricks, quirks and features of C

#105

Earlier quoted context omitted.

Fun fact about %n: The %n functionality also makes printf accidentally Turing-complete even with a well-formed set of arguments. A game of tic-tac-toe written in the format string is a winner of the 27th IOCCC. - sez wiki. A not so fun fact: Because the %n format is inherently insecure, it's disabled by default. - MSVC reference.

>The %n functionality also makes printf accidentally Turing-complete No it doesn't. Printf has no way to loop so it's not Turing complete. Even if you did what the IOCCC entry did with putting it into a loop it still wouldn't be Turing complete as it would not have an infinite memory.

Nothing real is "Turing complete" if it requires infinite memory. That's a property only abstract machines can have. In common parlance, something is Turing complete if it can compute arbitrary programs that can be computed with M bits of memory, where M is arbitrary but finite.

Re: Lesser known tricks, quirks and features of C

#106

Earlier quoted context omitted.

how would you iterate over every possible value of a unsigned int?

The unary complement operator should get you there: unsigned int x = 0; const unsigned int max = ~x; while (x Or, #include const unsigned int max = UINT_MAX;

Or if you only wanted to iterate halfway:

    unsigned int x = 0;

    while (x 
Or going down:

    unsigned int x = ~0;

    while (x > ~x) {
        calc(x--);
    }

Re: Lesser known tricks, quirks and features of C

#107

> volatile type qualifier > This qualifier tells the compiler that a variable may be accessed by other means than the current code (e.g. by code run in another thread or it's MMIO device), thus to not optimize away reads and writes to this resource. It's dangerous to mention cross-thread data access as a use case for volatile. In standard C, modifying any non-atomic value on one thread, while accessing it on another…

UB?

Re: Lesser known tricks, quirks and features of C

#108

> volatile type qualifier > This qualifier tells the compiler that a variable may be accessed by other means than the current code (e.g. by code run in another thread or it's MMIO device), thus to not optimize away reads and writes to this resource. It's dangerous to mention cross-thread data access as a use case for volatile. In standard C, modifying any non-atomic value on one thread, while accessing it on another…

UB?

„undefined behavior“

Re: Lesser known tricks, quirks and features of C

#109
post #77

Earlier quoted context omitted.

I think the problem with this is the C compiler has to find a solution which work with all the architectures it is expected to support. It order to achieve this, it must generalize in some areas and have flexibility in others. C programmers are required to be familiar with both the specifics of the architectures they are building for and the idiosyncrasies of their complier. I always assumed most other compiled langu…

> Bitfields in C can be manageable. For the use case of specifying a more efficient representation of a fiction confined to the program, then no harm, no foul. But the use case of specifying a hardware- or network- or ABI-specified data layout, then you need those bits in exactly the right spot, and the compiler should have no freedom whatsoever. (I'm thinking of the case of network protocol packets and hardware memo…

I’ve seen them used for hardware register access a lot. But there were usually a separate set of header files for when you are not using GCC/Clang - I didn’t look at those

Re: Lesser known tricks, quirks and features of C

#110

> volatile type qualifier > This qualifier tells the compiler that a variable may be accessed by other means than the current code (e.g. by code run in another thread or it's MMIO device), thus to not optimize away reads and writes to this resource. It's dangerous to mention cross-thread data access as a use case for volatile. In standard C, modifying any non-atomic value on one thread, while accessing it on another…

UB?

[deleted]
Post reply on HN