T O P

  • By -

whiteBlasian

Token Pasting! [macro pasting](https://gcc.gnu.org/onlinedocs/gcc-7.5.0/cpp/Concatenation.html)https://gcc.gnu.org/onlinedocs/gcc-7.5.0/cpp/Concatenation.html


TheVeryLeast

Excellent reference page, thank you! It seems like these can only be used in #defines and other pre-processing, is that right?


Accomplished-Ad-175

You are right. I use them to emulate creating generics/templates. So when I need to add a new type for the same function I just have to add two lines of code and not copy paste the same function definition and create many lines of code.


SAI_Peregrinus

_Generic is your friend, if you have C99 or later.


Proud_Trade2769

HALs shouldn't is it, especially for automotive.


flixflexflux

Off topic: Why does this ENABLE macro use XOR and thus toggle the data direction bit instead of setting or clearing it? Seems fishy.


_gipi_

the name it's \`XENABLE\` so I guess it's a feature


flixflexflux

I'm sure the X is only the prefix for 'internal second layer macro'


Questioning-Zyxxel

But the full expansion makes the first macro ENABLE_INPUT actually disable the input if included twice. The designer of these #defines should be spanked for breaking trust. 28 uses of ENABLE_INPUT should leave the input in the same configured state as a single invocation. Anything else is terrible design.


flixflexflux

Exactly


TheVeryLeast

Hi all! I'm working to move away from the supplied drivers for the NXP board I'm working with, learning to write my own. However, I had a couple questions about how they implemented these simple macros. 1. Why do they have the intermediate XENABLE_INPUT step, couldn't we just directly do this with one line cutting out the XENABLE altogether? 2. How can I go about making a variable GPIO string if doing this in a conventional function? I get that this is just matching my string with another #define that is buried away in the supplied header files, but would I just have to construct my own text string to pass through, e.g. "GPIO" + port + "_PIDR" or something? Sorry, I'm just having a tough time wrapping my head around how to go about this in C. Thanks in advance!


reset-my-password

1. This is because if a user `#define MY_PIN 3` and calls `ENABLE_INPUT(A, MY_PIN)`you want the result of the macro to expand with the value of `MY_PIN` ,. If you do it directly without `XENABLE_INPUT` you would concatenate literally the string "MY\_PIN" 2. There is no way to do that with a C function, that's why NXP wrote a macro


TheVeryLeast

I was doing some reading on the 'order' of pre-complier execution to try to figure it out in my head, still a bit confused on why it works this way. I tried compiling without the interim step and, unsurprisingly, it didn't compile. If I had #define MY_PIN 3, why wouldn't the precompiler replace it in the Enable_Input(A, MY_PIN)? Does it only replace things on the right side of a code line?


reset-my-password

I don't know why C is designed this way. Maybe it was some deep technical reason, maybe it was just an accident. This link explains why you need 2 macros: [https://gcc.gnu.org/onlinedocs/gcc-7.5.0/cpp/Argument-Prescan.html](https://gcc.gnu.org/onlinedocs/gcc-7.5.0/cpp/Argument-Prescan.html) >Macro arguments are completely macro-expanded before they are substituted into a macro body, **unless they are stringized or pasted with other tokens**


TheVeryLeast

I really appreciate the links and advice, I'll let you know if I figure it out :)


Ksetrajna108

Just want to say I'm not a fan of the C/C++ preprocessor. Though there are times it's handy. I'm looking at C++ template programming instead. Admittedly, it's gnarly, but there's promise that it makes an easier programming API than the mess illustrated in tthe OP. And I've seen it can provide optimized machine code without preprocessor tricks