Hacker News new | ask | show | jobs
by DSMan195276 3020 days ago
I would agree, if you take out the __declspec((dllimport) then it's just a 'static const restrict volatile long long int * ', which has lots of qualifications but isn't really much more then just a pointer to a `long long`. The qualifiers make it a bit harder to reason about, but that's also why people rarely use `restrict` and `volatile` in the first place.

I could be wrong but I think the above poster hasn't actually written tons of C, or else they would have picked a much more complicated example. If you throw a bunch of arrays, pointers, and function pointers in it quickly gets out of hand, like this:

    int (* const(*foo)(int (*)(int, int))[5])(void);
That thing defines 'foo', which is a pointer to a function who's first argument is a pointer to a function return a int and taking two ints as arguments, and returns a pointer to an array of 5 const function pointers which take no arguments and return an int.

Thankfully, you rarely run into something like that in the wild. And if you `typedef` the function pointers (Which is a pretty common now) it becomes tons easier to read.

1 comments

> That thing defines 'foo', which is a pointer to a function who's first argument is a pointer to a function return a int and taking two ints as arguments, and returns a pointer to an array of 5 const function pointers which take no arguments and return an int.

I find this much easier to understand than something with different keywords and qualifiers. Function pointers follow some simple rules to read, but can you be sure of what `volatile` implies ?

> I find this much easier to understand than something with different keywords and qualifiers. Function pointers follow some simple rules to read, but can you be sure of what `volatile` implies ?

Hmm, I suppose we just disagree then, which is fine. Things like `restrict` and `volatile` don't really bother me because:

1. The spots where people actually need to use them are very rare (`restrict` does have uses, but almost nobody uses it commonly. `volatile` has pretty much no correct uses outside of accessing registers in low-level code).

2. It's still just a pointer to a long long. I would need to look-up what __declspec((dllimport)) does, and I'd be highly suspicious of the use of `restrict` and `volatile` if it was not explained, but I still generally know what it is and how it can be used. Whereas with the example I gave, without staring for a long time or throwing it into a parser I can hardly tell what the type even is, let alone wrap my head around how it will be used.

>`volatile` has pretty much no correct uses outside of accessing registers in low-level code

Sorry, but what are you guys on about? You use "volatile" if you don't want the compiler to produce code that caches a variable. You use it all the time in embedded systems, or when writing multi-threaded code, etc. The usage of "volatile" is very clear, and should be well understood. "restrict" isn't used much because it's a c99 standard first of all, and second of all, it's like "inline"; it might make a difference, might not, and not a lot of people are in a situation where they have to shave off cycles.

> You use "volatile" if you don't want the compiler to produce code that caches a variable. You use it all the time in embedded systems, or when writing multi-threaded code, etc.

Thanks for providing a very nice exhibit of the confusion around this. Volatile is 99% useless for multithreading code (unless on MSVC which has a peculiar interpretation of the standard). See https://stackoverflow.com/a/4558031/1495627

It absolutely is not useless. You're the one confused. I never claimed it's a synchronization construct, or that it magically makes your code thread-safe.

No amount of fences or mutexes is going to help you if threads are operating on their own version of a variable that got cached in a register, or optimised away. You need to understand volatile to write correct multi-threaded code.

That StackOverflow answer is bogus, along with all the other comments. It's just a rant that, albeit correct, is barely related to the question asked, and it's a clear example why you shouldn't treat StackOverflow as more than an unreliable help forum. The guy asked about whether you should make variables shared inside of a critical section volatile. The answer is "yes, to prevent threads from working on stale data".

> No amount of fences or mutexes is going to help you if threads are operating on their own version of a variable that got cached in a register, or optimised away. You need to understand volatile to write correct multi-threaded code.

Any properly written Mutex or similar implementation is going to act as a full memory barrier and compiler barrier, meaning variables will already not be cached across lock/unlock. And if you're not properly taking your locks before accessing your variables, `volatile` is not going to save you. The fact is, if you're using a lock to protect a variable, marking it `volatile` gains you nothing and just slows your code down.

> "yes, to prevent threads from working on stale data".

`volatile` absolutely does not guarantee a variable doesn't contain 'stale' data. That's the entire reason you need memory barriers in the first place. Even through the compiler will read a `volatile` variable from memory every time, that memory may still have a stale value in the CPU cache, which `volatile` will do nothing to prevent. Only proper use of memory barriers ensures everyone is working on the same thing, which `volatile` does not do.

You do use it on embedded systems, hence my note about using it when accessing things like memory-mapped devices in low-level code (depending on what you're doing). However `volatile` is not at all correct for multi-threaded code and that's a very common misconception. It's really not correct for basically anything except for embedded systems.