Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Preprocessors and Macros

Name: Anonymous 2014-01-25 0:17

I have never encountered anything more pointless and stupid in my years of programming, EVER.

It's pretty much the only thing that holds me back from giving contributions to most open source C programs. Every source file is littered with #ifndefs every-fucking-where. 90% of the code is preprocessor directives and the rest is real C code. It's so fucking pointless and it's not even metaprogramming. I mean #define for using constants? Really? Can't you just use const for that? Sure, it's useful for separating your header files and relating functions in their source files but that's it. Dennis Ritchie should have just built that in the language. Sure, it's also useful compiling different lines of code for different kernel versions or different CFLAGS but whatever, it just proves how broken a programming language is.

What do you think /prog/? I've only parroting C shit, how does your favorite use macros?

Name: Anonymous 2014-01-25 0:21

So writing your programs to work on multiple platforms and take advantage of what those platforms offer is pointless? How should it be done?

Name: Anonymous 2014-01-25 0:44

Hate the playa' not the game.

Name: Anonymous 2014-01-25 0:59

I mean #define for using constants? Really? Can't you just use const for that?
Huh? That still reserves memory for them, even if it's read only.

Name: Anonymous 2014-01-25 1:05

As someone who uses C often, I can't contribute anything to open source projects for the same reason. How's that stopping you from working on your own projects, though? I thought CPP abuse was widely known as a nigger thing to do.

Macros are useful for making horrible looking functions/repetitive tasks less ugly, but that usually indicates a bigger underlying problem in your code and it's better to deal with that first.
I guess they're fine for inlining functions too, but isn't inline part of DA STANDARD?

I rarely use include guards because my shitty toy programs work without them (there's rarely any header that repeats anyway). In most cases you can be careful not to the include the same header twice and you're done. Not sure how it is for bigger projects, though.

Name: Anonymous 2014-01-25 1:32

Use an IDE or set up your editor so that it folds ifdefs automatically. Stop being a retard.

#define constants are fine, using const is for pointers, it's retarded anywhere else.

I use macros often to extend control statements in the language to apply to certain data structures better. The usage is clear from their naming scheme / examples.

C isn't ``broken'', you're just an idiot. You won't have a language as low as C, which is basically ``portable assembler'', without requiring some architecture and environment related code.

Not even FIOC and Java have 100% portable code, so fuck off.

Name: Anonymous 2014-01-25 2:43

>>5
isn't inline part of DA STANDARD

For C99 and C2011, and I think many major compilers will support you with inlining in C90 through __inline or a similar construction.

Name: Anonymous 2014-01-25 4:08

>>1
I don't get what the big deal is. That's just the way C works. If a project overuses ifdefs for portability instead of doing things right, then yes it sucks, but I've seen plenty of open source libraries that are fine without much of that. Take APR for example. They have split their cross-platform code up pretty well.

Name: Anonymous 2014-01-25 9:21

>>1
I mentioned a pretty useful preprocessor macro library in the foreache thread.

Name: Anonymous 2014-01-25 21:36

>>4
Aggressive generation of code that uses immediate values combined with linker garbage collection can totally eliminate the need to use the preprocessor for compile time constants. Nobody trusts compilers enough to actually do that, though.

>>7
There is however no portable way to force a function that is declared as inline to actually be inlined. In such cases the preprocessor is still the only option.

Name: Anonymous 2014-01-25 21:46

>>4
Aggressive generation of code that uses immediate values combined with linker garbage collection can totally eliminate the need to use the preprocessor for compile time constants. Nobody trusts compilers enough to actually do that, though.

>>7
There is however no portable way to force a function that is declared as inline to actually be inlined. In such cases the preprocessor is still the only option.

Name: Anonymous 2014-01-25 21:50

>>11
Trivial example, in case someone doesn't believe me:

/* test.c */
const int x = 42;
int main() { return x; }

gcc -fdata-sections -Wl,--gc-sections,--print-gc-sections test.c -o test 2>&1 | grep 'rodata\.x'
/usr/bin/ld: Removing unused section '.rodata.x' in file '/tmp/ccRmmxAg.o'

Name: Anonymous 2014-01-25 22:52

#define is pretty ugly, I wish C had real module and macro systems. That said, it's an extremely useful tool and your code is probably worse than it should be if you aren't making use of it.

I mean #define for using constants? Really? Can't you just use const for that?

I can't remember off the top of my head, but there actually are plenty of situations in C where it refuses to treat a const variable as an actual constant, because someone retard and used pointer arithmetic to modify a const variable. I don't remember if int nums[some_const_variable]; works, but I do know that _Static_assert(some_const_variable == 5); fails. You could also use an enum, but #define is the easiest and most flexible way to define constants.

#ifdefs is the most straightforward way to do cross-platform code in C. You can have a separate windows.c and unix.c file for the big differences, but for the little ones, this is so much easier:

#ifdef WINDOWS
// stupid bullshit
#else
// what every other operating system expects
#endif


X-macros are great for working with lots of constants, as well as parallel arrays. The idea there is you have a big file full of a macro invocations for an undefined macro, and then you define the macro in another just before you include the file full of data. Example:

// monster.i
MONSTER("bat", 5, 2);
MONSTER("mummy", 20, 10);
MONSTER("zombie", 15, 7);
MONSTER("dragon", 100, 30);

// monster.h
typedef struct monster_t {
const char *name;
int health, strength;
} monster_t;
#define MONSTER(name, health, strength) extern monster_t monster##name
#include "monster.i"
#undef MONSTER

// monster.c
#include "monster.h"
#define MONSTER(name, health, strength) monster_t monster_##name = { name, health, strength }
#include "monster.i"
#undef MONSTER


I didn't compile that, so there's probably some syntax errors and other fuckups, but you get the idea. You could maintain those definitions separately, but it's just more pointless work than necessary.

That was pretty easy to understand, but at some point, macros become black magic. See klib1, which implements efficient type-generic data structures in plain C. They're way more efficient than a vanilla C implementation, because they don't box the elements and they can specialize on the type (ie, the compiler can know that the data field for a hash table of struct foos is 16 bytes, instead of having to have that value passed in as a parameter to a function that operates on elements of any size). At the same time, I have a really hard time reading the source, which scares me.

tl;dr macros are useful. In an ideal world, we'd be doing our low level work in ``cisp,'' but this is the real world, so you have to put up with this shit if you don't want to go insane writing C.

[1] https://github.com/attractivechaos/klib

Name: Anonymous 2014-01-25 22:56

>>11
The portable way to force a function to be inlined is to make a little "myproject_inline" macro that selects whatever the compiler uses for its "ALWAYS_INLINE_YES_I_KNOW_JUST_FUCKING_DO_IT" attribute, and hope you never have to write software that runs on some rinky-dink microcontroller with only a C89 compiler written by illiterate Indians.

Name: Anonymous 2014-01-25 23:58

>>13
Nice tricks!

What do you mean by ``real module system''?

Name: not >>13 2014-01-26 10:00

>>15
Most presumably a way to assign functions to importable modules, make definitions easily locatable and allow partial imports. The way C (C++, too) does it right now is essentially automated copy and paste into a global namespace, which is one of the many reasons why C++ compilations are so incredibly slow. Personally, I like Haskell's module system save for records and think it would be a good fit for C. But we can't change that language anymore.

Name: Anonymous 2014-01-26 22:53

>>16
Personally, I like Haskell's module system [...] and think it would be a good fit for C. But we can't change that language anymore.

The Clang people seem to disagree:

http://clang.llvm.org/docs/Modules.html

Much less ambitious but still useful would be to add an option (e.g. --protoize-with-compile) for compilers to autogenerate headers as a side effect of compilation. It's silly that programmers still have to extract this sort of information from the sources by hand.

Name: Anonymous 2014-01-27 1:52

>>17
As much as I dislike Clang for being C++-centered and having the potential to kill GCC, I can't deny they churn out good stuff.

Regarding generated headers, I think this would be very inaccurate, and not just because the current compilation system barely distinguishes between files. Right now, the only way to have a hidden function of some sort is to declare and define it in a .c file while not declaring it in any header. Blindly generating headers would create a fair share of bogus prototypes.

Name: Anonymous 2014-01-27 15:25

>>18
Existing tools like cproto are smart enough to only generate declarations for non-static functions.

Data declarations, inline functions, and (of course) macros are harder since the language itself doesn't have a notion of exported vs. not exported where they are concerned. The makeheaders tool solves this problem using special preprocessor statements to mark what should go in the generated header and what shouldn't... but at that point you're halfway along the the Clang route of adding new language features anyway.

Name: Anonymous 2014-01-28 16:00

>>18
Wait what? You hate Clang for having the potential to kill GCC? So you not only hate compiler competition, but you actually are that much of a fanboy for GCC and I assume anything GNU? That's pretty shameful. I really do hope that Clang kills GCC.

Name: Anonymous 2014-01-28 16:04

>>18
Compiler competition commentary aside, isn't GCC pretty C++-focused itself these days?

Name: Anonymous 2014-01-29 14:05

>>21
Then, shouldn't it just rename itself to Cplang? As in ``See-plang".

Name: Anonymous 2014-01-29 14:20

SEPPLANG

Name: Anonymous 2014-01-29 16:38

>>20
While free software is a sound concept in my book, I'm no fanboy of GNU and definitely no enemy of compiler competition; I however do believe that replacing the main compiler of open-source/free software with a not copylefted one poses a threat to free software as a whole, and right now this is where Clang is heading. Especially in embedded programming, where many vendors wouldn't pass on the chance to use Clang for a proprietary compiler and sell it to those who want to use undocumented high-speed features, this could set us back a lot. I agree with rms when he says that this scheme effectively became extinct because of a strong, free compiler under copyleft.

>>21
Not that I know of, but making a Sepples compiler is a very hard task, so it wouldn't be surprising if most resources went there. GCC is a collection of compilers anyway, so I assume they have multiple teams for different languages, all with their respective amount of activity.

Name: Anonymous 2014-01-29 17:37

The GNU should have made a compiler usable by humans in the firstplace.
Clang is how old and its alot more usable than gcc.
The GNU realy deserves what it gets this time.

Name: Anonymous 2016-11-16 19:41

>>4
Macro constants just substitute literals into the source code before compiling, so they still take up memory. In fact, they might use MORE memory than using const, since each instance of a literal takes up its own memory (though this shouldn't be too hard for a compiler to optimize.

>>5
inline is just a hint, compilers aren't required to inline anything. Function-like macros are the only way to guarantee that something is inlined.

Name: Anonymous 2016-11-17 10:29

>>24
I however do believe that replacing the main compiler of open-source/free software with a not copylefted one poses a threat to free software as a whole
Please explain. Is this about a hypothetical fork of Clang that is distributed as non-free software and becoming more popular than Clang?

Name: Anonymous 2016-11-17 11:25

>>27
Oh shit, I didn't see the date of that post. I hope that anon is still around to respond to me.

Name: Anonymous 2016-11-17 21:00

True story. I write common code for phone apps with a rather delicious set of macros, and generate C++, Java and C# from that one source. It's absolutely disgusting, but at the same time is also rather brilliant. I may release it one day.

Name: Anonymous 2016-11-18 4:40

The most software running the world is C code held by dirty, hairy, primitive Neanderthal macros that should check their unhygienic privileges.

Name: Anonymous 2016-11-18 8:13

>>27
presumably, the point is that microcontroller manufacturers and OS vendors could make their own ENTERPRISE COMPILERS based on LLVM code without releasing the sources to the public, and they can't do that with GCC because of copyleft. it's a valid issue, although the nature of LLVM means that making an open source alternative to a proprietary compiler is easier than it would be otherwise: you need to translate LLVM bytecode, not wrtie a compiler from the scratch.

Name: Anonymous 2016-11-19 0:52

>>31
I don't quite understand what you're saying. Copyleft means that when you distribute the software, that software must also be available to the recipient as a work under copyleft. Are these companies (and vendors) going to distribute the free software under a proprietary software license?

it's a valid issue, although the nature of LLVM means that making an open source alternative to a proprietary compiler is easier than it would be otherwise: you need to translate LLVM bytecode, not wrtie a compiler from the scratch.
I'm completely missing the message here. I have no idea what this means.

Name: Anonymous 2016-11-19 1:19

Distribution of dubs

Name: Anonymous 2016-11-19 13:11

>>32
I think that it's quite clear what >>31-san meant.

Name: Anonymous 2016-11-20 6:43

>>31
The reason they can't do that with GCC is because GCC is a monolithic mess with no design made along the way, and the effort to clean that pile of shit up enough to have a proper modular system is enough that you may as well make a new compiler. Which is exactly how Clang\LLVM was made.

Name: Anonymous 2016-11-20 8:54

>>32
Are these companies (and vendors) going to distribute the free software under a proprietary software license?
they're going to make their compilers based on free software and distribute them under non-free licenses without sharing the sources. they can't do that in copyleft licenses like GPL because derivative work must be copylefted too.
I'm completely missing the message here. I have no idea what this means.
LLVM compilation is a two-step process - the compiler first creates a so-called intermediate representation ('LLVM bytecode') based on your source, then converts it to machine-specific assembly (e.g. x86 assembly, ARM assembly etc.). because of that, if an architecture you're targeting doesn't have an LLVM compiler, the only thing you need to write is the second stage: bytecode to machine code. getting bytecode from source code is already done (at least for C and C++).

Name: Anonymous 2016-11-21 2:36

#include <stdio.h>

#define a main b
#define b () c
#define c { d
#define d printf e
#define e ( f
#define f "anus\n" g
#define g ) h
#define h ; i
#define i }

int a

Name: Anonymous 2016-11-21 8:55

>>37
direct threaded code

Name: Anonymous 2016-11-21 13:41

>>37
VALID C CODE

Name: Anonymous 2016-11-21 22:19

VALID GRUNNUR CODE

#include <stdio.h>
#define s(s) #s
#define GRUNNUR s(GRUNNUR)
int main() {
puts(GRUNNUR);
return 0;
}

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List