C++ assignment - stylish or performance? - c

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.

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)

How to do short circuit print in C?

Hello everybody: I've an expression like this:
if (a == 1) {
printf("hello\n");
}
Is there a way to do something like that?
a== 1 && printf("hello\n");
It's called short-circuit expression, but I don't know anything about it. Does it exist in C? How to do it.
As already pointed out in comments, doing a == 1 && printf("hallo\n"); will indeed work as I believe you intended, i.e. "hallo" will only be printed if the condition is true, if a is 1 in this case. The short answer is yes, short-circuit expressions do exist in C.
This can be easily determined by compiling and running the code, which is the recommended way if you're just exploring how the language works. However, if the question is, "is it good practice to use it to decide when to print?", many people would say no. It's best to stick to more readable, and therefore more maintainable code, with the if statement in your example.
A word of warning here:
it works as long as the expression to the right hand side of && returns sth convertible to boolean, e.g. printf in this case returns an int. It is valid C code, true, but seems a code smell to me and many people would complain during the review.
Note also, that sth like this:
void foo(char*)
{
//whatever
}
int main(void)
{
int a = 1;
a == 1 && foo("abc");
}
is not going to to work and you'll have to use some tricks, e.g. with comma operator:
a == 1 && (foo("abc"),1);
Thus, for the sake of maintainability, you might want to use some other construct, e.g. the ternary operator:
printf(a==1?"Hello\n":"");
which is not exactly equivalent, but might (or might not) work better in your particular case.
EDIT:
as per comment below:
It is true, that passing conditional input to printf's format string can be considered a bad practice, especially in more complicated cases as rids one of compiler diagnostics related to printf's input params.
#chqrlie suggested just using a one-liner if: if(a==1)printf("hello\n"); which is fine as long as coding conventions allow it. Sometimes they don't.
If so, the somewhat cleaner ternary version is this: printf("%s",a==1? "Hello\n":"");. Please note however this is all matter of coding conventions/programmer's and reviewer's taste/linter settings/insert-your-source-of-good-practices-here. Thus, one can most likely skin this cat in way more ways, and the list is definitely not exhaustive.

Assigning the result of fopen inside an if statement

I am learning C currently and wanted to know whether the following two pieces of code perform differently, or if it's just a style thing.
Looking at some sources they the have the following code:
...
FILE * pFile;
pFile = fopen ("myfile.txt","r");
if (pFile == NULL)
{ some code }
...
While my professor has the following code in his notes:
...
FILE * pFile
if ((pFile = fopen("myfile.txt","r")) == NULL)
{ some code }
...
Just wanted to know if this is merely a style preference by different programmers or if there is an advantage to putting the return/set line inside the if statmeent.
There is no difference. More experienced programmers sometimes go with the second form, just to save a line, but they are essentially identical. The second tends to be a little more "UNIX-y", where most function calls are checked for error (as opposed to success) before continuing.
They're identical, since (pFile = fopen("myfile.txt", "r")) returns pFile, but I would personally prefer the first since it's more explicit.
These two variants are equal. It doesn't affect performance. However, I think the first variant is better because it makes things more clear.
Both programs are equivalent.
Some people favor the first style saying it is more readable and some people favor the second style saying it is more compact.
For information, note that in some coding guidelines (MISRA being one) the second style is forbidden. MISRA forbids the use of the assignment operator in the controlling expression of the if statement.
There is no difference in performance, but the second is clearly preferable.
The first separates attempting to open the file from testing for success in opening the file.
The second makes opening the file and testing for success a single operation, which is exactly how you should not only code it, but also how you should think about it. You shouldn't think of them as two separate operations at all. The operation of opening a file is not complete until/unless you've checked whether it opened correctly or not.
Treating opening and testing as two separate operations is lazy coding that leads to sloppy thinking. Don't do it.
As said here the two segments are clearly identical. I would however prefer the first as it tends to avoid the confusion between the assignment operator = and the equality operator ==. Consider a situation in which there's a function foo(arg) returning an int. You would write something like:
int y;
if ((y = foo(x)) == 0) {
... some code ...
}
Now, let's say you confuse the assignment operator with equality (very common in if expressions BTW):
int y;
if ((y == foo(x)) == 0) {
... some code ...
}
Since the type of the expression (y == foo(x)) is int, the above is considered a legitimate C code by the compiler. This would clearly produce a bug in your code.
Now, lets consider the first option:
int y;
y = foo(x);
if (y == 0) {
... some code ...
}
Clearly, now you are less likely to confuse the assignment with the equality. Furthermore, even if you do write y == foo(x); as a statement the compiler will issue a warning.
While the existing answers are very good, I've got a couple things to add about how to approach the question of whether something in C is a performance issue.
First, a quick way to check is to compile both versions of the code with gcc -O3 and compare the generated .o files. If they're identical, then of course there cannot be any performance difference (at least not with the current compiler/version you're using).
With that said, a more conceptual approach to the question is to ask yourself 2 questions:
Do the two pieces of code define exactly the same behavior for all possible valid input variable values, or only the same behavior (or even just similar behavior) for the inputs you expect?
If they define exactly the same behavior, do you think it's easy for a compiler to see this?
If so, there "shouldn't" be a performance difference, because the compiler "should" compile them both to whatever it thinks is the most efficient way to achieve the behavior described. Of course sometimes compilers can be pretty stupid, so if it really matters, you may want to check.
In your case, both versions of the code define the exact same behavior, and I think you'd have a hard time finding a compiler that compiled them differently, except perhaps with optimization completely disabled.

When should you use macros instead of inline functions?

In a previous question what I thought was a good answer was voted down for the suggested use of macros
#define radian2degree(a) (a * 57.295779513082)
#define degree2radian(a) (a * 0.017453292519)
instead of inline functions. Please excuse the newbie question, but what is so evil about macros in this case?
Most of the other answers discuss why macros are evil including how your example has a common macro use flaw. Here's Stroustrup's take: http://www.research.att.com/~bs/bs_faq2.html#macro
But your question was asking what macros are still good for. There are some things where macros are better than inline functions, and that's where you're doing things that simply can't be done with inline functions, such as:
token pasting
dealing with line numbers or such (as for creating error messages in assert())
dealing with things that aren't expressions (for example how many implementations of offsetof() use using a type name to create a cast operation)
the macro to get a count of array elements (can't do it with a function, as the array name decays to a pointer too easily)
creating 'type polymorphic' function-like things in C where templates aren't available
But with a language that has inline functions, the more common uses of macros shouldn't be necessary. I'm even reluctant to use macros when I'm dealing with a C compiler that doesn't support inline functions. And I try not to use them to create type-agnostic functions if at all possible (creating several functions with a type indicator as a part of the name instead).
I've also moved to using enums for named numeric constants instead of #define.
There's a couple of strictly evil things about macros.
They're text processing, and aren't scoped. If you #define foo 1, then any subsequent use of foo as an identifier will fail. This can lead to odd compilation errors and hard-to-find runtime bugs.
They don't take arguments in the normal sense. You can write a function that will take two int values and return the maximum, because the arguments will be evaluated once and the values used thereafter. You can't write a macro to do that, because it will evaluate at least one argument twice, and fail with something like max(x++, --y).
There's also common pitfalls. It's hard to get multiple statements right in them, and they require a lot of possibly superfluous parentheses.
In your case, you need parentheses:
#define radian2degree(a) (a * 57.295779513082)
needs to be
#define radian2degree(a) ((a) * 57.295779513082)
and you're still stepping on anybody who writes a function radian2degree in some inner scope, confident that that definition will work in its own scope.
For this specific macro, if I use it as follows:
int x=1;
x = radian2degree(x);
float y=1;
y = radian2degree(y);
there would be no type checking, and x,y will contain different values.
Furthermore, the following code
float x=1, y=2;
float z = radian2degree(x+y);
will not do what you think, since it will translate to
float z = x+y*0.017453292519;
instead of
float z = (x+y)+0.017453292519;
which is the expected result.
These are just a few examples for the misbehavior ans misuse macros might have.
Edit
you can see additional discussions about this here
if possible, always use inline function. These are typesafe and can not be easily redefined.
defines can be redfined undefined, and there is no type checking.
Macros are relatively often abused and one can easily make mistakes using them as shown by your example. Take the expression radian2degree(1 + 1):
with the macro it will expand to 1 + 1 * 57.29... = 58.29...
with a function it will be what you want it to be, namely (1 + 1) * 57.29... = ...
More generally, macros are evil because they look like functions so they trick you into using them just like functions but they have subtle rules of their own. In this case, the correct way would be to write it would be (notice the paranthesis around a):
#define radian2degree(a) ((a) * 57.295779513082)
But you should stick to inline functions. See these links from the C++ FAQ Lite for more examples of evil macros and their subtleties:
inline vs. macros
macros containing if
macros with multiple lines
macros used to paste two tokens together
The compiler's preprocessor is a finnicky thing, and therefore a terrible candidate for clever tricks. As others have pointed out, it's easy to for the compiler to misunderstand your intention with the macro, and it's easy for you to misunderstand what the macro will actually do, but most importantly, you can't step into macros in the debugger!
Macros are evil because you may end up passing more than a variable or a scalar to it and this could resolve in an unwanted behavior (define a max macro to determine max between a and b but pass a++ and b++ to the macro and see what happens).
If your function is going to be inlined anyway, there is no performance difference between a function and a macro. However, there are several usability differences between a function and a macro, all of which favor using a function.
If you build the macro correctly, there is no problem. But if you use a function, the compiler will do it correctly for you every time. So using a function makes it harder to write bad code.

Resources