Hacker News new | past | comments | ask | show | jobs | submit login

The C preprocessor is arguably a not type safe language unto itself.



The C preprocessor is a siren song, lures people in with the promise of "extra performance/features/structures for zero runtime cost!" but murders any readability or rationality within your codebase.

Cool concept, but once you've dealt with any legacy codebase that has used it extensively, it feels like an anti-pattern/footgun. Ultimately you just want the language to do those things directly and for the compiler to be smart enough to optimize it later.

Essentially it is too clever for its own good.


No one likes the preprocessor, but it's practicaly required if you don't want to move to C++ with template metaprogramming.


I do like the preprocessor and my major pet peeve with C is that the preprocessor has been stagnant for ages. Like, why the hell can't i do something like

    #define BASE hey
    #define HEADERS foo bar baz
    #append HEADERS bad bal bah
    #push OSSUFFIX
    #ifdef WIN32
    #define OSSUFFIX win32
    #else
    #define OSSUFFIX unknown
    #endif
    #foreach H HEADERS
    #eval include "$(BASE)/$(OSSUFFIX)/$(HEADERS)"
    #endfor
    #pop OSSUFFIX
People go to great lengths making all sorts of weird structures from x-macros, repeated statements, defines that only exist to be used by other defines, etc all to work around existing preprocessor limitations - and many of them would simply become unnecessary if the preprocessor could do things like variable editing, loops and being able to eval its own commands.

Even though some stuff can be done via language features, it is often necessary and more flexible to work with the source code itself.


One alternative is to just write a C code generator, which lets you mix C and some sensible language, eg. python. Then use that to generate the code which is then sent to gcc.


Well, C++ templates happen on the preprocessor too.


No they don't. Template instantiation happens during compilation, way later than the preprocessor.


Not really? They're part of compilation and obey all the type rules & syntax of the language. They're not textual replacements that run in a distinctly different phase like macros are.


where in hell did you learn that, this is entirely false


Well, it is today.

When I first learned C++, using cfront in the late 80's, lots of the language was implemented as C pre-processor macros.


maybe lots of the language, but not templates. Cfront 2 did not have templates, and Cfront 3 did have them without using the preprocessor.

You can even check out how it was done: https://github.com/seyko2/cfront-3/blob/master/src/template....


Its not too clever for its own good, its programmers that are too clever for C, and desperately need basic features, and its the only way to get them unless you switch language.

Its also surreally poorly designed, encouraging worse habits than C itself. Avoiding definition collisions and lack of namespaces alone make it horrific for any moderate sized project and up. Combine that with the near complete lack of static analysis tools, and its a recipe for disaster.


Yeah, I do agree. Interestingly, you could argue that it's fairly strongly typed; at least according to some definitions (and btw "type-strength" is not a rigidly defined term, so the definition itself is somewhat debatable).

I don't claim to be an expert in knowing what is/isn't in the various standards; I just look at the build errors and static analysis alarms. That said, I think the argument is that in the vast majority of cases it's not actually possible to change the type of a variable; off the top of my head, I can only think of pointer co-erosion. Otherwise, if you define an unsigned int, it stays an unsigned int.

Now strong/weak typing isn't necessarily the same thing as type safety. C has always seemed astonishingly bad on that front. It's like they try to trick novice developers into thinking they have a robust type system sometimes.

If you define functions implicitly they will link to any symbol, EVEN A VARIABLE... this is bananas. I think I sort of understand why compilers work this way, but it really feels like a bug in the language. Under some compilers you might not even get a warning for implicit function, either! TI had a compiler that hid them by default.

Enums are garbage in C. Again, you can misuse them, and may not even get a warning. You can pass an enum for color to a function that takes an enum for kittens and the compiler will be happy as a clam. The way they're often used can cause constant implicit conversions every time there's an assign/compare. May not be a problem for most positive values, but it's annoying if you're trying to develop standard compliant code. MISRA defines an "essential type system" and normal enums usage violates it.

I'm probably forgetting a TON of deficiencies. Please add them or correct me where I'm wrong.


"arguably" is not needed. Preprocessor destroys most of the semantics and even some syntax of C.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: