I'm pretty much positive about this, but just to be on the safe side:
Does the C standard guarantee that AND chains (A && B && ...) will be evaluated left to right, and that evaluation will stop as soon as there's a 0?
Same question for OR. (As soon as there's a 1)
Can I count on this for other C-style languages?
Is this code safe:
if (somePtr!=NULL && somePtr->someMember==123)
{
...
}
Yes, it is guaranteed for C, C++ and C#. The same goes for Delphi with "short curcuit evaluation" enabled.
This is behaviour numerous lines of code rely on to this moment.
Yes, it is standardised by both C and C++.
Yes, your assumptions about the order of operations in C are correct and the code snippet will work as intended. I would take other "C-style" languages on a case-by-case basis.
Yes it does.
I have seen people who thought that was unclear, and replaced &&'s with this form:
if (a)
if (b)
if (c)
if (d) {
}
Personally I think that's kinda ugly.
Related
I am working on embedded C. Could somebody help me which piece of code?
Is efficient in terms of robustness, memory as well as Misra friendly?
Code1:
if (func() == 1 || func() == 2) {
/* Body of the function */
}
Code2:
locvar = func();
if (locvar == 1 || locvar == 2) {
/* Body of the function */
}
As noted, the two examples may do different things and give different results.
MISRA-C compliance and robustness go hand in hand. As for memory use, it's not an issue in this code.
The first example is likely not robust nor MISRA compliant: specifically, MISRA-C:2012 rule 13.5 bans the right operand of && and || from containing persistent side effects.
Furthermore, rules like 12.1 requires sub expressions of large expressions to be surrounded by parenthesis, to make operator precedence explicit.
A MISRA-C compliant version would be something like:
locvar = func();
if ((locvar == 1) || (locvar == 2)) {
...
}
Further to #Lundin's answer, the only MISRA C:2012 consideration is if there is a persistent side-effect within func() - if there are no persistent side-effects then MISRA C has little to say.
Likewise from a code efficiency perspective, an efficient compiler will (probably) optimise the code - it may even inline the function body anyway...
For me, the primary consideration would be code readability (and hence maintainability) - a single call makes it clear what you are doing... and if there are no persistent side-effects what is to be gained from making a second function call?
I vote for Code 2.
In theory, computing the value used in the branch condition can improve branch prediction for the processor, but an optimizing compiler should do this for you. In think this answer might be interesting:
conditional data transfers VS n conditional control transfers(using conditional mov) in Assembly
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.
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.)
I would like to know if this looks correct :
while((next !=NULL) && (strcmp(next->name, some_string) < 0) {
//some process
}
I mean, if next is NULL, then the second part of the expression won't be ever tested by the compiler? I have heard that in C++ it's the case (but I'm not even sure of it).
Can someone confirm me that I won't get strange errors on some compilers with that?
Yes && is short circuited and you are using it correctly.If next is NULL string compare will never happen.
Yes, in C++ short circuit and and or operators are available.
Here's a question answered in the C-faq on the subject.
It's definitely the case in both C and C++.
This will work with lazy evaluation (the second statement not evaluated if the first one is evaluated to "false") unless your compiler is so non-standard compliant it can't even be named a C compiler. Millions lines of code in the field rely on this behavior, so you can think that this behavior is just guaranted.
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.