using macros for equal and and operators - c

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.)

Related

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)

Macro redefining logical operators

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?

Redefinition of Assignment Operator

It is in my understanding that several languages use := as the assignment operator. This is implemented to possibly avoid any confusion with the == operator. This seemed like a very valid point to me, so I was thinking of how to implement it in a language like C. Here is what I was thinking.
#define := =
// ... later on
int x := 4;
Although this would work (if the preprocessor supported that syntax), it would still allow me to get away with using the = operator. So my question is, Is there a way to "flag" a symbol or operator / Is there a way to prevent the use of some defined operator or symbol? Again, here is what I was thinking, but I don't know about the syntactical / semantical legality of this.
#undef =
#define := =
A macro name can only be an identifier. I'd be quite surprised if any C compiler accepted that definition. In principle, a compiler could accept it as a language extension, but gcc, for example, does not. Any conforming C compiler must at least issue a diagnostic.
You say it works; I'm frankly skeptical. What compiler are you using?
#undef =
Same problem.
I can see (and even agree with) your point that using := rather than = for the assignment operator would have been a better idea. But using the preprocessor to alter the language like this, even in cases where it works, is rarely a good idea.
C programmers know that = means assignment. Anyone reading your code can probably guess that := is meant to be assignment, but it would just make your code that much harder to read.
Standard C does not allow the '=' assignment operator to be undefined, or changed. However, the source code to several C compilers is available; and you are welcome to make your own modifications to your build of a C compiler. Including changing '=' to ':='. Good luck!
Good question, but don't do that. Your method results in bad readability.

"with" macro in C

I was looking for a macro that will resemble the with-construct.
The usage should be something like:
with (lock(&x), unlock(&x)) {
...
}
It might be useful for some other purposes.
I came up with this macro:
#define __with(_onenter, _onexit, v) \
for (int __with_uniq##v=1; __with_uniq##v > 0; )\
for (_onenter; __with_uniq##v > 0; _onexit) \
while (__with_uniq##v-- > 0)
#define _with(x, y, z) __with(x, y, z)
#define with(_onenter, _onexit) _with(_onenter, _onexit, __COUNTER__)
It has 3 nested loops because it should:
Initialize loop counter (C99 only, of course)
Possibly initialize variable _onenter (such as with (int fd=open(..), close(fd)))
Allow break inside the code block. (continue is allowed too. And the macro could be adjusted to assert() it out)
I used it on the code for the XV6 OS and it seems quite useful.
My question is - what are the worst problems with such a macro? I mean, besides the mere usage of a C macro (especially one that implements new control-flow construct).
So far have found these drawbacks / problems:
No support for return or goto (but it can save some gotos in kernel code)
No support for errors (such as fd < 0). I think this one is fixable.
gnu89 / c99 and above only (loop counter. the unique variable trick is not necessary)
Somewhat less efficient than simple lock-unlock. I believe it to be insignificant.
Are there any other problems? Is there a better way to implement similar construct in C?
That macro scares me. I'd prefer the traditional approach using gotos.
That approach is primitive, but most C programmers are familiar with the pattern and if they're not, they can understand it by reading the local code. There is no hidden behavior. As a consequence, it's pretty reliable.
Your macro is clever, but it would be new to most everybody and it comes with hidden gotchas. New contributors would have to be thought rules such as "don't return or goto out of a with block" and "break will break out of the with block, not out of the surrounding loop". I fear mistakes would be common.
The balance would shift if you could add warnings for misuses of this construct to the compiler. With clang, that seems to be an option. In this case, misuses would be detected and your code would remain portable to other compilers.
If you're willing to restrict yourself to GCC and Clang, you can use the cleanup attribute. That would make your example look like this:
lock_t x = NULL __attribute__((cleanup(unlock)));
lock(&x);
And unlock will be called with a pointer to the variable when it goes out of scope. This is integrates with other language features like return and goto, and even with exceptions in mixed C/C++ projects.

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