
P99: Preprocessor Macros and Functions for C99 and C11 (2012) - fanf2
http://p99.gforge.inria.fr/p99-html/index.html
======
Aardwolf
I have the experience that to be truly compatible with everything that
potential users of your code would like to use (embedded systems, ...) one
still needs to write C90, what's your experience with this and where are C99
and C11 used the most?

~~~
flohofwoe
(not the author) I'm writing my C headers in the "common subset of C99 that
compiles both in C and C++ mode on clang, gcc and MSVC".

This subset is basically a post-C90, pre-C99 version of C which has most
convenience-extensions which existed before C99, like declaring variables in
the middle of a scope block, allowing to declare the loop variable inside
for(), etc...

I tried to port my header libraries to "pure" C90, but I didn't enjoy
programming at all in this. The mid-90's pre-C99 C is almost like a new
language compared to ISO C90.

I'm using C for very small cross-platform programs targeting WebAssembly,
e.g.:

[https://floooh.github.io/sokol-html5/](https://floooh.github.io/sokol-html5/)

[https://floooh.github.io/tiny8bit/](https://floooh.github.io/tiny8bit/)

~~~
xvilka
MSVC was a pain until the 2015 version. Now writing C99 is safe if you target
it. Microsoft did immense harm to the industry though, by not supporting C99
until recently. Many Windows-only programmers I saw not even aware of C99 and
C11 features, sigh... Anyway, there is no reason to use MSVC at all. Both
Google and Mozilla switched[1][2] to use clang-cl[3], which is a drop-in
replacement for MSVC cl. Moreover, it supports various sanitizers - ASAN,
UBSAN, etc for Windows platform. MSVC didn't even have support for inline
assembly! A piece of crap, not a compiler. Just use clang-cl instead.

[1] [http://blog.llvm.org/2018/03/clang-is-now-used-to-build-
chro...](http://blog.llvm.org/2018/03/clang-is-now-used-to-build-chrome-
for.html)

[2] [https://blog.mozilla.org/nfroyd/2019/04/25/an-unexpected-
ben...](https://blog.mozilla.org/nfroyd/2019/04/25/an-unexpected-benefit-of-
standardizing-on-clang-cl/)

[3]
[https://clang.llvm.org/docs/MSVCCompatibility.html](https://clang.llvm.org/docs/MSVCCompatibility.html)

~~~
kazinator
> _Microsoft did immense harm to the industry though, by not supporting C99
> until recently._

That's overblown. I don't use C99 myself, other than the odd library function.
I don't like most of the C99 and C11 features.

I was following ISO C very closely in the time frame surrounding C99; but I
lost interest in ISO C as such after that disappointment.

~~~
cryptonector
Designated initializers are very important. As a maintainer of a codebase that
has to support older Windows OSes and MSVC releases, I still suffer from not
being able to use them.

Really, GP is correct, MSFT did immense harm by not implementing more/all of
C99 sooner. I'm still quite annoyed by that even now, even now that MSFT has
finally started doing amazing things.

~~~
kazinator
> _Designated initializers are very important._

I use macros or functions to initialize structures. When a new member is added
that must be initialized to a non-default value, I can add a parameter to the
intializer, and then the compiler finds all the places where an argument must
be added.

I could easily work this gradually into an old code base that I have to
maintain.

Such an initializer macro can be implemented itself using designated
initializers, but that is of low value; it's in one place, next to where the
struct is declared.

The designated initializer clearly wins if we have to declare a large, sparse
array without executing code, and initialize just a few entries to nonzero
which are not close to the beginning.

~~~
cryptonector
If you're using cscope/etags/an IDE then you want the field name to be visible
where the assignment is made, otherwise finding your way around a codebase
with many function dispatch tables can get painful.

~~~
kazinator
I have a macro or function name that occurs wherever the struct is
initialized.

    
    
      struct point p = point_init(x, y);
    

ctags will find the definition of point_init, and cscope all the occurrences.

Random code throughout the program that is not related to the data type's
module shouldn't be performing explicit low-level member-for-member
initializations of the data type, even with a safer mechanism like designated
initializers.

~~~
cryptonector
Yes, but if you have a struct with many functions then you still have a
problem. With designated initializers I can traverse all the paths through
cscope alone.

~~~
kazinator
I can't even begin to imagine a foggy gist of what you might be talking about,
but it seems very real to you.

~~~
cryptonector
I should do an asciicinema thing, I guess. Point is, I can search for
assignments to any one function-typed fieldname of a struct and find all the
functions that are reachable through instances of that struct.

~~~
kazinator
Are we (still) talking about C here? Initialization isn't assignment in C;
structure elements are called "members" and they cannot be functions.

------
kbumsik
Doesn't it need a (2012) tag? Also where's the code I can download?

~~~
mikeash
Source is available here:
[http://p99.gforge.inria.fr/](http://p99.gforge.inria.fr/)

