Macro redefining logical operators - c

I'm new to C programming so please forgive me if this sounds like a dumb thing to do.
I had an idea in attempt to make my code a bit more readable and the idea is to #define logical operators such as #define OR ||.
If anyone can direct me is this bad or good practice, is it common etc... and also if it has any side effects, I would be grateful.
Thanks in advance.

Alternate names for this and other operators are already part of standard C. Using #include <iso646.h> defines:
Name
Replacement
and
&&
and_eq
&=
bitand
&
bitor
|
compl
~
not
!
not_eq
!=
or
||
or_eq
|=
xor
^
xor_eq
^=

Don't.
A C coder is expected to read such operators like it was plain English. And also, you would not do the same for the operators +, -, / and *, right? Logicians does not write or. They use symbols. So instead, just get used reading them.
If I saw the expression if(x OR y) in a piece of code, my first thought would be "This must be a beginner" and my next thought would be "Did they do it right and used || or did they use a single |?" I better check this up just to make sure.
is it good practice
My opinion is definitely no
is it common
No, because most C coders share my opinion
and also if it has any side effects
Not really. It's a macro, so it's simple cut and paste.
And just for completeness. It does exist a standard header that does what you want called iso646.h. But it's rarely used. I had never seen it before Eric posted his answer. So if you want to do this, then use that header instead of reinventing the wheel.

Never use Macros without prefix
see the answer of klutt
What's more readable:
(a + b) * c
(a PLUS b) MULT c
If you want to make code more readable, do that on a higher level, e.g.
if ((x >= y) && (x < z))
implement a function/macro with a meaningful naming, e.g.
#define IN_RANGE(X, MIN, MAX) ((X) >= (MIN)) && ((X) < (MAX))
if (IN_RANGE(x, min, max))

If anyone can direct me is this bad or good practice, is it common etc... and also if it has any side effects, I would be grateful. Thanks in advance.
It is not common practice, and in my experience it creates maintenance problems (such as doing a global search and replace to change an "and" to an "or" in several string literals and breaking code because someone else decided to use and instead of && and or instead of ||).
Straight C code can be a bit eye-stabby, and generations of programmers have tried to use the preprocessor to redefine operators or delimiters to something easier to read (such as Pascal programmers redefining { and } as BEGIN and END, Fortran programmers redefining && and || to AND and OR, etc.). The problem is no two programmers do it the same way, and you just wind up with an unmaintainable mess. Then an experienced C programmer comes in, says "what's all this garbage", and rips it all out anyway, like I wound up doing after the situation I described above.
Resist the urge to create macros for standard delimiters and operators. You just make your code harder to understand and maintain for other C programmers.

#define logOR ||
#define bitOR |
This may be the one reason why here symbols were chosen, as with + etc. There is not one "or", so it gets lost in a sea of variable names.
side effect:
if (x||y)
if (xORy)
The xORy one does not work - unless such variable is declared, which would be very confusing, in combination.
_eq
#define or_eq |=
Now this is actually the argument against it; or= and or = do not work, so good-bye to the assignment operator = also.
a = a PLUS 4 // acceptable - an assignment
a PLUS_EQ 4 // ??? assembler?

Related

Define custom syntax "until" in C

I expect I can do something like this:
int i = 0;
until (i == 2){
printf("yes\n");
i++;
}
Without telling detail about what until does, I'm sure reader know what is the algorithm from code above. Yes I know I can just use while(!condition){}.
The output will be:
yes
yes
So is it possible that I can achieve my goal?
I feel macro able to do this with define or something else. But I'm lack of knowledge about preprocessing directive syntax in C
#define until <what should I fill here>
Edit:
Many people triggered from what am I doing. I'm sorry for if I bother you guys. Don't worry, this syntax is just for my self only. So I hope I don't bother code reader who accidentally read my code or C priest.
First of all, and I can't stress this enough: making your own secret, private language using function-like macros is a cardinal sin in C. It is perhaps the worst thing you can ever do.
Why? Because other people reading your code are expected to know C. They are however not expected to know your secret private macro language. Furthermore, they have absolutely no interest in learning your secret private macro language.
So please never do things like this in real programs.
That being said, you pretty much already answered the question yourself:
#define until(condition) while(!(condition))
Note that condition, being a function-like macro parameter, should be placed inside a parenthesis. This prevents accidental operator precedence bugs. For example if the caller passes until(i + 1) then you want it to loop while(!(i+1)) and not while(!i + 1).
From Expert C Programming:
Macro use is best confined to naming literal constants,
shorthand for a few well-chosen constructs. Define the macro name all
in capitals so that, in use, it's instantly clear it's not a function
call. Shun any use of the C preprocessor that modifies the underlying
language so that it's no longer C.
Re: "I'm sure reader know what is the algorithm from code above."
No, it would confuse one even more as the keyword until is not part of the C language. It doesn't take much to type a few extra characters.
That being said, you could do:
#define until(condition) while(!(condition))
Compile your program with:
gcc -E -nostdinc main.c
to see what changes the preprocessor made.
But it would still be an abomination, and not something one would condone.
Using until is useful in select cases.
Sometimes an algorithm or software contract uses until in its definition, so it is good to see that match in code.
Yet re-writing language semantics adds confusion and maintenance costs.
Consider a comment when until is needed.
int i = 0;
// until (i == 2) {
while (i != 2) {
printf("yes\n");
i++;
}
Yes, you can use define for that. See the following example for the macro definition
#include <stdio.h>
#define until(x) while(!(x))
int main() {
int i = 0;
until (i == 2){
printf("iteration %d\n", i);
i++;
}
return 0;
}
If you run it, the output would be
iteration 0
iteration 1
I don't know why you would do this, until is a mostly abandoned keyword for a reason. But this should work:
#define until(cond) while (!(cond))

MISRA2012 Rule 12.1 Extra parentheses recommended

I'm trying to fix the compliance of my code to misra C. During the static analysis, I had this violation:
Rule 12.1: Extra parentheses recommended. A conditional operation is
the operand of another conditional operator.
The code is:
if (CHANNEL_STATE_GET(hPer, channel) != CHANNEL_STATE_READY)
{
retCode = ERROR;
}
where CHANNEL_STATE_GET is a macro as follow:
#define CHANNEL_STATE_GET(__HANDLE__, __CHANNEL__)\
(((__CHANNEL__) == CHANNEL_1) ? (__HANDLE__)->ChannelState[0] :\
((__CHANNEL__) == CHANNEL_2) ? (__HANDLE__)->ChannelState[1] :\
((__CHANNEL__) == CHANNEL_3) ? (__HANDLE__)->ChannelState[2] :\
((__CHANNEL__) == CHANNEL_4) ? (__HANDLE__)->ChannelState[3] :\
((__CHANNEL__) == CHANNEL_5) ? (__HANDLE__)->ChannelState[4] :\
(__HANDLE__)->ChannelState[5])
Do you have any idea to solve this violation?
BR,
Vincenzo
There's several concerns here, as far as MISRA C is concerned:
There's various rules saying that macros and complex expressions should be surrounded by parenthesis, and that code shouldn't rely on the C programmer knowing every single operator precedence rule. You can solve that by throwing more parenthesis on the expression, but that's just the top of the iceberg.
The ?: operator is considered a "composite operator" and so expressions containing it are considered "composite expressions" and come with a bunch of extra rules 10.6, 10.7 and 10.8. Meaning that there is a lot of rules regarding when and how this macro may be mixed with other expressions - the main concerns are implicit, accidental type conversions.
The use of function-like macros should be avoided in the first place.
Identifiers beginning with multiple underscores aren't allowed by the C language since it reserves those for the implementation (C17 7.1.3).
The easier and recommended fix is just to forget about that macro, since it will just cause massive MISRA compliance headache. Also at a glance, it looks like very inefficient code with nested branches. My suggested fix:
In case hPer happens to be a pointer to pointer (seems like it), then dereference it and store the result in a plain, temporary pointer variable. Don't drag the nasty pointer to pointer syntax around across the whole function/macro.
Replace this whole macro with a (inline) function or a plain array table look-up, depending on how well you've sanitized the channel index.
Ensure that CHANNEL_1 to CHANNEL_5 are adjacent integers from 0 to 4. If they aren't, use some other constant or look-up in between.
A MISRA compliant re-design might look like this:
typedef enum
{
CHANNEL_1,
CHANNEL_2,
CHANNEL_3,
CHANNEL_4,
CHANNEL_5
} channel_t;
// state_t is assumed to be an enum too
state_t CHANNEL_STATE_GET (const HANDLE* handle, channel_t channel)
{
if((uint32_t)channel > (uint32_t)CHANNEL_5)
{
/* error handling here */
}
uint32_t index = (uint32_t)channel;
return handle[index];
}
...
if (CHANNEL_STATE_GET(*hPer, channel) != CHANNEL_STATE_READY)
If you can trust the value of channel then you don't even need the function, just do a table look-up. Also note that MISRA C encourages "handle" in this case to be an opaque type, but that's a chapter of its own.
Note that this code is also assuming that HANDLE isn't a pointer hidden behind a typedef as in Windows API etc - if so then that needs to be fixed as well.
Note (as more or less implied by Lundins comment....), I answer more about how to approach MISRA findings (and those of a few other analysis tools I suffered from ....).
I would first try to get a better angle on what the finding is actually describing. And with a nested structure like shown, that takes some re-looking. So ...
I would apply indentation, just to make life easier while editing and then, well, add some more () in inviting places, e.g. in this case so as to enclose each x?y:z into one pair.
#define CHANNEL_STATE_GET(__HANDLE__, __CHANNEL__)\
( ((__CHANNEL__) == CHANNEL_1) ? (__HANDLE__)->ChannelState[0] :\
( ((__CHANNEL__) == CHANNEL_2) ? (__HANDLE__)->ChannelState[1] :\
( ((__CHANNEL__) == CHANNEL_3) ? (__HANDLE__)->ChannelState[2] :\
( ((__CHANNEL__) == CHANNEL_4) ? (__HANDLE__)->ChannelState[3] :\
(((__CHANNEL__) == CHANNEL_5) ? (__HANDLE__)->ChannelState[4] :\
(__HANDLE__)->ChannelState[5] \
) \
) \
) \
) \
)
This is to address what the quoted finding is about.
I would not feel bad about sprinkling a few more around e.g. each CHANNEL_N.
(I admit that I did not test my code against a MISRA checker. I try to provide an approach. I hope this fixes the mentioned finding, possibly replacing it with another one.... MISRA in my experience is good at that.... I do not even expect this to solve all findings.)
When trying to fix some seriously odd code like this, it's often a good idea to take one or two big steps backwards.
We know that hPer refers to an array. We have some troublesome code that is indexing into that array and pulling out one of the channel states. But this code is, frankly, pretty awful. Even if the MISRA checker weren't complaining about it, any time you've got five nested ?: operators, performing a cumbersome by-hand emulation of what ought to be a simple array lookup, it's a sure sign that something isn't right, and that there's probably a better way to do it. So what might that better way be?
One way to approach that question is to ask, How is the ChannelState array filled in? And is there any other code that also fetches out of it?
You've only asked us about this one line that your MISRA checker is complaining about. That suggests that the code that fills in the ChannelState array, and any other code that fetches out of it, is not drawing complaints. Perhaps that other code accesses the ChannelState array in some different, hopefully better way. Perhaps the underlying problem is that the programmer who wrote this CHANNEL_STATE_GET macro was unaware of that other code, had not been properly educated on this program's coding conventions and available utility routines. Perhaps it's perfectly acceptable to directly index a ChannelState array using a channel value. Or perhaps there's already something like the map_channel_index function which I suggested in my other answer.
So, do yourself a favor: spend a few minutes seeking out some other code that accesses the ChannelState array. You might learn something very interesting.
Other comments and answers are suggesting replacing the cumbersome CHANNEL_STATE_GET macro with a much simpler array lookup, and I strongly agree with that recommendation.
It's possible, though, that the definitions of CHANNEL_1 through CHANNEL_5 are not under your control, such that you can't guarantee that they're consecutive small integers as would be required. In that case, I recommend writing a small function whose sole job is to map a channel_t to an array index. The most obvious way to do this is with a switch statement:
unsigned int map_channel_index(channel_t channel)
{
switch(channel) {
case CHANNEL_1: return 0;
case CHANNEL_2: return 1;
case CHANNEL_3: return 2;
case CHANNEL_4: return 3;
case CHANNEL_5: return 4;
default: return 5;
}
}
Then you can define the much simpler
#define CHANNEL_STATE_GET(handle, channel) \
((handle)->ChannelState[map_channel_index(channel)])
Or, you can get rid of CHANNEL_STATE_GET entirely by replacing
if(CHANNEL_STATE_GET(hPer, channel) != CHANNEL_STATE_READY)
with
if((*hPer)->ChannelState[map_channel_index(channel)] != CHANNEL_STATE_READY)

using macros for equal and and operators

Recently refreshed my self on C language. From some of the blogs, i have read operators such as "==" and '&&' lead to error prone where programmers use '=' and '&' respectively, instead , and programmers spent lot of time to find and fix the issues.
i think that defining macros for "==" and "&&" will solve the issue.
#define EQ ==
#define AND &&
int main(void)
{
int a = 1 , b = 2 ;
if(a EQ 1 AND b EQ 2 ){
// some statements
}
}
is it clutter the readability ? is there any other solution to solve this issue ?
Personally I prefer not to touch the very fundamental syntax of the language, like creating macros to replace C keywords or operators.
In this case it is pretty simple, and may not alter much the readability, but other programmers (if you are not the only one maintaining the code) seeing those macros may be tempted to create other macros for something else they think is ambiguous or error prone.
So I would not endorse macros at the keywords / operators level in C.
But you may use some compiler options to show when there is an ambiguity, like
gcc -Wall prog.c -o prog
having Wall enabling all warnings (you can refine the warnings with gcc). This depends upon the compiler you are using.
For instance
int a=1,b=2;
if (a = b) { ... }
would give a warning having gcc as compiler with the -Wall option.
that's a bad idea
the best thing to do is compile with all warning flags activated (-Wall) and make sure that you can compile your code without warnings
and TDD. It's more about practices that the syntax
I would recommend the book "Code Complete"
To attempt to re-define the C language is always a very bad idea. To replace operators through macros will make the code unreadable to other C programmers.
Regarding && accidentally turning into &, I doubt it is an issue, at least I have never encountered that problem. There is already alternative logical operators in standard C, you should use those if anything.
The header <iso646.h> defines the following eleven macros (on the
left) that expand to the corresponding tokens (on the right):
and &&
and_eq &=
bitand &
bitor |
compl ~
not !
not_eq !=
or ||
or_eq |=
xor ^
xor_eq ^=
The idea of == being dangerous is a terribly old-fashioned idea. In the 80s, confused programmers invented obscure rules like "always put the literal in front of the variable when doing comparison", i.e if (0 == var).
The correct way to avoid bugs related to this is to avoid assignment inside conditions. Once you have adopted that as good coding style, dodging such bugs is easy. To spot them has been a non-issue since the release of Turbo C in 1990. Since then, pretty much every single compiler has been able to warn for "possibly incorrect assignment" when you made an assignment inside an if statement.
In modern programming, all professional programmers use static analyser tools to spot all kinds of compile time bugs. If your compiler for some reason is unable to spot this bug, then the static analyser certainly will.
So to answer your question: yes it is clutter and makes the code more error-prone and less readable.
Actually, I don't think there is a problem here. Any modern compiler will issue a warning if something fishy will be detected.
No, it's not a particularly good idea. It means that any experienced C programmer reading your code has to find out what EQ and AND mean before he can read your code.
Sure, == can be error-prone, but IMHO the best solution to that problem is to (a) turn on warnings in your compiler, and (b) be careful.
(The standard header <iso646.h> provides a macro and that expands to &&, but it doesn't provide a macro for ==. The point of <iso646.h> was to support systems on which certain characters are difficult to use due to old national variant character sets, not to provide more readable alternatives.)

Using a macro for a small operation, is this good practice?

I have a small piece of code that requires to read 4-bit values bitpacked in a 32-bit integer. Since I need to call this operation several times, even if it's simple, I require max speed on it.
I was pondering about macros and inline functions, thus I made this macro:
#define UI32TO4(x, p) (x >> ((p - 1) *4) & 15)
And I have an inline function that does the same thing.
static inline Uint8 foo_getval(Uint32 bits, int pos){
return (bits >> ((pos-1)*4)) & 15;
}
Considering the simplicity of the operation, and that the values are already prepared for this call (so no possibility of calling on the wrong types, or pass values that are too big or that stuff), what would be the best one to use? Or, at least, the most comprehensible for someone else potentially reading/modifying the code later on?
EDIT! Forgot to mention, I am using C99.
The function is safer. Your assumptions that the values are always "right" only holds while you're developing that code. You can't tell if someone down the line (or yourself when you're tired) won't pass unexpected values.
The compiler will do the inlining when it sees it as effective. Use type-safe functions whenever you can, use macros only when you have no other practical choice.
I would use the inline function because macros can cause unwanted side effects. Use macros only to save typing if necessary.
If a macro name is the same name as a function name in an other compilation unit you would get strange compilation errors. These problems can be hard to find, especially if the macro is expanded elsewhere and no error occurs.
Additionally a function warns you about parameter types and would not let you give a double for pos. The macro could allow this.
It's late, and I'm grumpy (and I'll probably delete this post later) but I get tired of hearing the same arguments against macros parroted over and over again (a double redundacy):
Joachim Pileborg (above) states "using a function allows the compiler to do better typechecking". This is often stated, but I don't believe it. With macros, the compiler already has all the available type information at its fingertips. Functions simply destroy this. (And possibly destroy optimization, by pushing registers out to the stack, but that's a side issue.)
And frast (above) states "macros can cause unwanted side effects". True--but so can functions. I think the rule is to always use UPPER_CASE for macros which don't have function semantics. This rule has often been broken. But it doesnt apply here: the OP has redundantly used both uppercase and function semantics.
But I would suggest a tiny improvement. The OP has quite correctly placed parentheses around the whole macro, but there should also be parentheses around each argument:
#define UI32TO4(x, p) ((x) >> (((p) - 1) * 4) & 15)
Always enclose your macro args in parentheses, unless you are doing string or token concatenting, etc.
Macros are, of course, dangerous, but so are functions. (And the less said of STL, the better).

C++ assignment - stylish or performance?

Having been writing Java code for many years, I was amazed when I saw this C++ statement:
int a,b;
int c = (a=1, b=a+2, b*3);
My question is: Is this a choice of coding style, or does it have a real benefit? (I am looking for a practicle use case)
I think the compiler will see it the same as the following:
int a=1, b=a+2;
int c = b*3;
(What's the offical name for this? I assume it's a standard C/C++ syntax.)
It's the comma operator, used twice. You are correct about the result, and I don't see much point in using it that way.
Looks like an obscure use of a , (comma) operator.
It's not a representative way of doing things in C++.
The only "good-style" use for the comma operator might be in a for statement that has multiple loop variables, used something like this:
// Copy from source buffer to destination buffer until we see a zero
for (char *src = source, *dst = dest; *src != 0; ++src, ++dst) {
*dst = *src;
}
I put "good-style" in scare quotes because there is almost always a better way than to use the comma operator.
Another context where I've seen this used is with the ternary operator, when you want to have multiple side effects, e.g.,
bool didStuff = DoWeNeedToDoStuff() ? (Foo(), Bar(), Baz(), true) : false;
Again, there are better ways to express this kind of thing. These idioms are holdovers from the days when we could only see 24 lines of text on our monitors, and squeezing a lot of stuff into each line had some practical importance.
Dunno its name, but it seems to be missing from the Job Security Coding Guidelines!
Seriously: C++ allows you to a do a lot of things in many contexts, even when they are not necessarily sound. With great power comes great responsibility...
This is called 'obfuscated C'. It is legal, but intended to confuse the reader. And it seems to have worked. Unless you're trying to be obscure it's best avoided.
Hotei
Your sample code use two not very well known by beginners (but not really hidden either) features of C expressions:
the comma operator : a normal binary operator whose role is to return the last of it's two operands. If operands are expression they are evaluated from left to right.
assignment as an operator that returns a value. C assignment is not a statement as in other languages, and returns the value that has been assigned.
Most use cases of both these feature involve some form of obfuscation. But there is some legitimate ones. The point is that you can use them anywhere you can provide an expression : inside an if or a while conditional, in a for loop iteration block, in function call parameters (is using coma you must use parenthesis to avoid confusing with actual function parameters), in macro parameter, etc.
The most usual use of comma is probably in loop control, when you want to change two variables at once, or store some value before performing loop test, or loop iteration.
For example a reverse function can be written as below, thanks to comma operator:
void reverse(int * d, int len){
int i, j;
for (i = 0, j = len - 1 ; i < j ; i++, j--){
SWAP(d[i], d[j]);
}
}
Another legitimate (not obfuscated, really) use of coma operator I have in mind is a DEBUG macro I found in some project defined as:
#ifdef defined(DEBUGMODE)
#define DEBUG(x) printf x
#else
#define DEBUG(x) x
#endif
You use it like:
DEBUG(("my debug message with some value=%d\n", d));
If DEBUGMODE is on then you'll get a printf, if not the wrapper function will not be called but the expression between parenthesis is still valid C. The point is that any side effect of printing code will apply both in release code and debug code, like those introduced by:
DEBUG(("my debug message with some value=%d\n", d++));
With the above macro d will always be incremented regardless of debug or release mode.
There is probably some other rare cases where comma and assignment values are useful and code is easier to write when you use them.
I agree that assignment operator is a great source of errors because it can easily be confused with == in a conditional.
I agree that as comma is also used with a different meaning in other contexts (function calls, initialisation lists, declaration lists) it was not a very good choice for an operator. But basically it's not worse than using < and > for template parameters in C++ and it exists in C from much older days.
Its strictly coding style and won't make any difference in your program. Especially since any decent C++ compiler will optimize it to
int a=1;
int b=3;
int c=9;
The math won't even be performed during assignment at runtime. (and some of the variables may even be eliminated entirely).
As to choice of coding style, I prefer the second example. Most of the time, less nesting is better, and you won't need the extra parenthesis. Since the use of commas exhibited will be known to virtually all C++ programmers, you have some choice of style. Otherwise, I would say put each assignment on its own line.
Is this a choice of coding style, or does it have a real benefit? (I am looking for a practicle use case)
It's both a choice of coding style and it has a real benefit.
It's clearly a different coding style as compared to your equivalent example.
The benefit is that I already know I would never want to employ the person who wrote it, not as a programmer anyway.
A use case: Bob comes to me with a piece of code containing that line. I have him transferred to marketing.
You have found a hideous abuse of the comma operator written by a programmer who probably wishes that C++ had multiple assignment. It doesn't. I'm reminded of the old saw that you can write FORTRAN in any language. Evidently you can try to write Dijkstra's language of guarded commands in C++.
To answer your question, it is purely a matter of (bad) style, and the compiler doesn't careā€”the compiler will generate exactly the same code as from something a C++ programmer would consider sane and sensible.
You can see this for yourself if you make two little example functions and compile both with the -S option.

Resources