In Visual Studio the assert macro is defined like this:
#define assert(expression) (void)( \
(!!(expression)) || \
(_wassert(_CRT_WIDE(#expression), _CRT_WIDE(__FILE__), (unsigned)(__LINE__)), 0) \
)
I get that the right part after || is only evaluated if the left expression is false, and throws an exception.
I have 3 questions:
The !! double negation is to convert the 'expression' type to bool, right? What would happen if they were left out? The 'expression would be implicitly converted to bool when it's logically or'ed with another expression, right? In:
float() || /* Call function that throws*/;
The float() is converted to bool type anyway?
2.After the || operator we have:
( /* call function that throws */ , 0 )
The comma is a sequence point, so first the function is called and then this expression is evaluated as 0. If the function call didn't terminate the program then the expression would simply be:
!!(expression)) || 0
What's the point of that 0 after the comma? If if weren't there, then the expression would be:
!!(expression)) || / * call function that throws */
Which is the same thing, right?
And finally the (void), I'm wondering what this is for.
Let's break down the code:
#define assert(expression) (void)( \
(!!(expression)) || \
(_wassert(_CRT_WIDE(#expression), _CRT_WIDE(__FILE__), (unsigned)(__LINE__)), 0) \
)
The (void) is to squelch the compiler warning that the expression result is unused. And also ensures that the assert is not accidentally used as part of a larger expression.
The !! part of the !!(expression) is to ensure that the expression evaluates to false or true.
But mischievous C++ code could have overridden operator! and cause a bit of chaos here.
Why C-style cast, and not static_cast<bool>? I suspect the same header file is used to support C and C++, and possibly C++/CLI as well. (If so, could be justification to use static_cast<bool> for C++, and (bool) for C in two language specific macros.)
If the expression object has an operator bool conversion, it will be used by the !!. (But would also have been used by (bool)(expression).)
Regardless, the observation that the !! is unnecessary seems correct to me. Expressions in C++ that are truthy (non-zero) or falsy (zero) is part-and-parcel to the language.
The (x(), 0) comma operator is used because the x (in this case the _wassert) returns a void. Can't do an a || b if the b is void, so the trickery just makes it so the void is called, and the expression results in an int. It does not matter that it is 0.
The _wassert does not throw. It may abort with exit code 3. It may break into the debugger.
It may be ignored and continue. And with the assert having been violated there could be a broken axle consequences, or the code may have some defensive programming to handled the assert violation.
Since the assert function-like macro was written as an expression, it neatly avoids the problem of the "dangling if macro" (had an if (!(expression)) ... construct been used), and is an expression rather than a statement.
Related
In some code i found the following line:
CPPUNIT_ASSERT(1, val.getBytefield().size());
Does this really compare the two parameters for equality? Normally, i would expect this comparison with CPPUNIT_ASSERT_EQUAL:
CPPUNIT_ASSERT_EQUAL(1, val.getBytefield().size());
The test compiles and the assertion works in case 1, but not in case 2. Where is the difference?
This just looks like broken code to me, probably the result of some refactoring or other editing that was done.
The CPPUNIT_ASSERT macro takes a single argument—a condition expression—and asserts that that condition is true (i.e., fails if it is false).
This code is attempting to pass two arguments, but rather than functioning as an argument delimiter here, the comma is actually working as the (somewhat obscure) comma operator. The comma operator evaluates its first operand, discards the result, and then evaluates to the result of the second operand. Therefore, the initial 1 is an irrelevant no-op. The code is equivalent to:
CPPUNIT_ASSERT(val.getBytefield().size());
which means that it's asserting that the byte field has a non-zero size.
Obviously, this is different from your second snippet of code:
CPPUNIT_ASSERT_EQUAL(1, val.getBytefield().size());
which asserts that the byte field's size is exactly equal to 1.
It seems like you are using a compiler has an extension, which accepts 2 parameters to a single argument macro. I guess it's MSVC, see this
Hence, the macro will check if the first argument is true or not, in your case, it's 1, which is contextual converted to the bool value true, by this expansion
#define CPPUNIT_ASSERT(C) \
( CPPUNIT_NS::Asserter::failIf( !(C), \
CPPUNIT_NS::Message( "assertion failed", \
"Expression: " #C), \
CPPUNIT_SOURCELINE() ) )
You can double check my statement by change:
CPPUNIT_ASSERT(1, val.getBytefield().size());
with:
CPPUNIT_ASSERT(1000, val.getBytefield().size());
CPPUNIT_ASSERT_EQUAL(1, val.getBytefield().size());
From my experiment, .size() will likely return a std::size_t. From the definition of CPPUNIT_ASSERT_EQUAL:
#define CPPUNIT_ASSERT_EQUAL(expected,actual) \
(assertEquals((expected), \
(actual), \
CPPUNIT_SOURCELINE(), \
"" ) )
and assertEquals:
template<class T>
void assertEquals ( const T & expected,
const T & actual,
SourceLine sourceLine,
const std::string & message
)
Because type of 1 (int) and return type of .size() (std::size_t) is different, then no matching function can be found, the compiler can not compile your code.
I think this is the solution:
CPPUNIT_ASSERT(1 == val.getBytefield().size());
CPPUNIT_ASSERT_EQUAL(std::size_t(1), val.getBytefield().size());
I have a habit of using the following syntax in my compile-time flags:
#if (defined(A) & defined(B))
It's usually suggested that I do it with the && as follows:
#if (defined(A) && defined(B))
I know the difference between the two operators, and that in normal code && would short-circuit. However, the above is all handled by the compiler. Does it even matter what I use? Does it affect compile time by some infinitesimal amount because it doesn't evaluate the second define()?
Since defined(SOMETHING) yields 0 or 1, so that you're guaranteed 0 or 1 on both sides, it doesn't make a technical difference whether you use & or &&.
It's mostly about good habits (using & could carry over to some situation where it would be wrong) and about writing code that is easy to grasp by simple pattern matching. A & in there causes a millisecond pause while one considers whether it possibly could be a bit-level thing.
On the third hand, you can't use keyword and, which you ¹can use in ordinary C++ code.
Notes:
¹ With Visual C++ you can use and via a forced include of <iso646.h>.
According to the C99 standard, the expressions used in the preprocessor are constant expressions as defined by the C language itself, and are evaluated using the same engine. Therefore, && is a logical and operator that short circuits based on its LHS, and & is a bitwise operator with no predefined order of evaluation.
In practical terms, when used with defined() as you are, there is no difference between the two. However, the following would show a difference:
#define A 2
#define B 5
#if (A && B)
printf("A && B\n");
#endif
#if (A & B)
printf("A & B"\n);
#endif
In this case, A && B will be output, but not A & B (since the result of that bitwise-and is 0)
I would like to add to the previous answers that it can actually matter a lot in a situation like this:
#define A 0
#define B 21
#if (A != 0) && (42 / A == B)
/* ... */
#endif
Here, if A == 0, the compiler will not break. Writing (A != 0) & (42 / A == B) will make the compiler complain about a division by zero.
Sometimes a local variable is used for the sole purpose of checking it in an assert(), like so -
int Result = Func();
assert( Result == 1 );
When compiling code in a Release build, assert()s are usually disabled, so this code may produce a warning about Result being set but never read.
A possible workaround is -
int Result = Func();
if ( Result == 1 )
{
assert( 0 );
}
But it requires too much typing, isn't easy on the eyes and causes the condition to be always checked (yes, the compiler may optimize the check away, but still).
I'm looking for an alternative way to express this assert() in a way that wouldn't cause the warning, but still be simple to use and avoid changing the semantics of assert().
(disabling the warning using a #pragma in this region of code isn't an option, and lowering warning levels to make it go away isn't an option either...).
We use a macro to specifically indicate when something is unused:
#define _unused(x) ((void)(x))
Then in your example, you'd have:
int Result = Func();
assert( Result == 1 );
_unused( Result ); // make production build happy
That way (a) the production build succeeds, and (b) it is obvious in the code that the variable is unused by design, not that it's just been forgotten about. This is especially helpful when parameters to a function are not used.
I wouldn't be able to give a better answer than this, that addresses that problem, and many more:
Stupid C++ Tricks: Adventures in assert
#ifdef NDEBUG
#define ASSERT(x) do { (void)sizeof(x);} while (0)
#else
#include <assert.h>
#define ASSERT(x) assert(x)
#endif
As of C++17, the variable can be decorated with an attribute.
[[maybe_unused]] int Result = Func();
assert( Result == 1 );
See https://en.cppreference.com/w/cpp/language/attributes/maybe_unused for details.
This is better than the (void)Result trick because you directly decorate the variable declaration, rather than add something as an afterthought.
You could create another macro that allows you to avoid using a temporary variable:
#ifndef NDEBUG
#define Verify(x) assert(x)
#else
#define Verify(x) ((void)(x))
#endif
// asserts that Func()==1 in debug mode, or calls Func() and ignores return
// value in release mode (any braindead compiler can optimize away the comparison
// whose result isn't used, and the cast to void suppresses the warning)
Verify(Func() == 1);
int Result = Func();
assert( Result == 1 );
This situation means that in release mode, you really want:
Func();
But Func is non-void, i.e. it returns a result, i.e. it is a query.
Presumably, besides returning a result, Func modifies something (otherwise, why bother calling it and not using its result?), i.e. it is a command.
By the command-query separation principle (1), Func shouldn't be a command and a query at the same time. In other words, queries shouldn't have side effects, and the "result" of commands should be represented by the available queries on the object's state.
Cloth c;
c.Wash(); // Wash is void
assert(c.IsClean());
Is better than
Cloth c;
bool is_clean = c.Wash(); // Wash returns a bool
assert(is_clean);
The former doesn't give you any warning of your kind, the latter does.
So, in short, my answer is: don't write code like this :)
Update (1): You asked for references about the Command-Query Separation Principle. Wikipedia is rather informative. I read about this design technique in Object Oriented Software Construction, 2nd Editon by Bertrand Meyer.
Update (2): j_random_hacker comments "OTOH, every "command" function f() that previously returned a value must now set some variable last_call_to_f_succeeded or similar". This is only true for functions that don't promise anything in their contract, i.e. functions that might "succeed" or not, or a similar concept. With Design by Contract, a relevant number of functions will have postconditions, so after "Empty()" the object will be "IsEmpty()", and after "Encode()" the message string will be "IsEncoded()", with no need to check. In the same way, and somewhat symetrically, you don't call a special function "IsXFeasible()" before each and every call to a procedure "X()"; because you usually know by design that you're fulfilling X's preconditions at the point of your call.
You could use:
Check( Func() == 1 );
And implement your Check( bool ) function as you want. It may either use assert, or throw a particular exception, write in a log file or to the console, have different implementations in debug and release, or a combination of all.
With C++17 we can do:
[[maybe_unused]] int Result = Func();
though it involves a bit of extra typing compared to a assert substitution. See this answer.
Note: Added this because is the first google hit for "c++ assert unused variable".
You should move the assert inside the function before the return value(s). You know that the return value is not an unreferenced local variable.
Plus it makes more sense to be inside the function anyway, because it creates a self contained unit that has its OWN pre- and post-conditions.
Chances are that if the function is returning a value, you should be doing some kind of error checking in release mode on this return value anyway. So it shouldn't be an unreferenced variable to begin with.
Edit, But in this case the post condition should be X (see comments):
I strongly disagree with this point, one should be able to determine the post condition from the input parameters and if it's a member function, any object state. If a global variable modifies the output of the function, then the function should be restructured.
Most answers suggest using static_cast<void>(expression) trick in Release builds to suppress the warning, but this is actually suboptimal if your intention is to make checks truly Debug-only. The goals of an assertion macro in question are:
Perform checks in Debug mode
Do nothing in Release mode
Emit no warnings in all cases
The problem is that void-cast approach fails to reach the second goal. While there is no warning, the expression that you've passed to your assertion macro will still be evaluated. If you, for example, just do a variable check, that is probably not a big deal. But what if you call some function in your assertion check like ASSERT(fetchSomeData() == data); (which is very common in my experience)? The fetchSomeData() function will still be called. It may be fast and simple or it may be not.
What you really need is not only warning suppression but perhaps more importantly - non-evaluation of the debug-only check expression. This can be achieved with a simple trick that I took from a specialized Assert library:
void myAssertion(bool checkSuccessful)
{
if (!checkSuccessful)
{
// debug break, log or what not
}
}
#define DONT_EVALUATE(expression) \
{ \
true ? static_cast<void>(0) : static_cast<void>((expression)); \
}
#ifdef DEBUG
# define ASSERT(expression) myAssertion((expression))
#else
# define ASSERT(expression) DONT_EVALUATE((expression))
#endif // DEBUG
int main()
{
int a = 0;
ASSERT(a == 1);
ASSERT(performAHeavyVerification());
return 0;
}
All the magic is in the DONT_EVALUATE macro. It is obvious that at least logically the evaluation of your expression is never needed inside of it. To strengthen that, the C++ standard guarantees that only one of the branches of conditional operator will be evaluated. Here is the quote:
5.16 Conditional operator [expr.cond]
logical-or-expression ? expression : assignment-expression
Conditional expressions group right-to-left. The first expression is
contextually converted to bool. It is evaluated and if it is true, the
result of the conditional expression is the value of the second
expression, otherwise that of the third expression. Only one of these
expressions is evaluated.
I have tested this approach in GCC 4.9.0, clang 3.8.0, VS2013 Update 4, VS2015 Update 4 with the most harsh warning levels. In all cases there are no warnings and the checking expression is never evaluated in Release build (in fact the whole thing is completely optimized away). Bare in mind though that with this approach you will get in trouble really fast if you put expressions that have side effects inside the assertion macro, though this is a very bad practice in the first place.
Also, I would expect that static analyzers may warn about "result of an expression is always constant" (or something like that) with this approach. I've tested for this with clang, VS2013, VS2015 static analysis tools and got no warnings of that kind.
The simplest thing is to only declare/assign those variables if the asserts will exist. The NDEBUG macro is specifically defined if asserts won't be effected (done that way round just because -DNDEBUG is a convenient way to disable debugging, I think), so this tweaked copy of #Jardel's answer should work (cf. comment by #AdamPeterson on that answer):
#ifndef NDEBUG
int Result =
#endif
Func();
assert(Result == 1);
or, if that doesn't suit your tastes, all sorts of variants are possible, e.g. this:
#ifndef NDEBUG
int Result = Func();
assert(Result == 1);
#else
Func();
#endif
In general with this stuff, be careful that there's never a possibility for different translation units to be build with different NDEBUG macro states -- especially re. asserts or other conditional content in public header files. The danger is that you, or users of your library might accidentally instantiate a different definition of an inline function from the one used inside the compiled part of the library, quietly violating the one definition rule and making the runtime behaviour undefined.
This is a bad use of assert, IMHO. Assert is not meant as an error reporting tool, it's meant to assert preconditions. If Result is not used elsewhere, it's not a precondition.
Certainly you use a macro to control your assert definition, such as "_ASSERT". So, you can do this:
#ifdef _ASSERT
int Result =
#endif /*_ASSERT */
Func();
assert(Result == 1);
int Result = Func();
assert( Result == 1 );
Result;
This will make the compiler stop complaining about Result not being used.
But you should think about using a version of assert that does something useful at run-time, like log descriptive errors to a file that can be retrieved from the production environment.
I'd use the following:
#ifdef _DEBUG
#define ASSERT(FUNC, CHECK) assert(FUNC == CHECK)
#else
#define ASSERT(FUNC, CHECK)
#endif
...
ASSERT(Func(), 1);
This way, for release build, the compiler don't even need to produce any code for assert.
If this code is inside a function, then act on and return the result:
bool bigPicture() {
//Check the results
bool success = 1 != Func();
assert(success == NO, "Bad times");
//Success is given, so...
actOnIt();
//and
return success;
}
// Value is always computed. We also call assert(value) if assertions are
// enabled. Value is discarded either way. You do not get a warning either
// way. This is useful when (a) a function has a side effect (b) the function
// returns true on success, and (c) failure seems unlikely, but we still want
// to check sometimes.
template < class T >
void assertTrue(T const &value)
{
assert(value);
}
template < class T >
void assertFalse(T const &value)
{
assert(!value);
}
I haven't succeeded in using [[maybe_unused]] but
you can use the unused attribute
int Result __attribute__((__unused__)) = Func();
gcc Variable-Attributes
I've been familiar with the ternary operator for quite some time now, and have worked with it in a few differnet languages. My understanding of the operator is this:
condition ? expr1 : expr2
However, in C++, the following code is legal:
int i = 45;
(i > 0) ? i-- : 1;
Aren't you, in effect, just writing 1; or i - 1;How is this a complete statement? I understand that the intention of the code is to decrement i if it's greater than 0, but I would've thought that the code would generate a compiler error as just being an expression, not a full statement. I expected code like this:
int i = 45;
i = (i > 0) ? i - 1 : i;
This is called expression statement. The expression is evaluated and its value is discarded.
Even this is valid:
42;
although it does nothing. Only side effects (like i--, assignment, etc) in the expression have effects.
In fact, many statements we use are expression statements: assignments, function calls, etc:
a = 42;
foo();
That is a valid expression. You might have received a warning because you are not saving the result of the expression, but that you have the i-- your statement does have an effect.
In C++, an expression like 1 is a perfectly valid statement with no side effects. You could very feasibly write this function:
void f() {
1;
}
In fact, even this is correct.
void f() {
;;;;
}
A literal statement evaluates its arguments but does nothing more. The system views 1; as being just like func();. The only difference is that while func(); would logically have some side effects, 1; does not so it ends up being a no-op. The ternary operator evaluates like an if-statement, so the second form is only evaluated if the operand is true. Thus:
(i > 0) ? i-- : 1;
If i is greater than 0, the second form is evaluated. When it is evaluated, it carries its side effect, which decrements i by 1. Otherwise, the third form is evaluated, which does nothing. Although this block of code works, it is not incredibly readable, so while it's nice toy code a real if-statement is ideal for situations like this. For the same reason, this line would have the same effect but be frowned upon for being equally unreadable.
((i > 0) && (i--)) || 1;
Assuming you didn't overwrite the boolean operators, this code will short-circuit and behave like the ternary operator. If i is not greater than 0, then the && need not evaluate its second operand since the && is false, but the || must since it might be true. Inversely, if i is greater than 0, the && needs to evaluate but the || already knows it's true.
Aren't you, in effect, just writing 1; or i - 1;
No: i-- is not the same as i - 1. In the first case, the value of i is modified. In the second case it is not.
In the event that i less than or equal to zero, then you're correct that the resulting 'code' will be 1. However, the compiler will realise that this is not a useful thing to execute and so it ought to generate code equivalent to:
if( i > 0 ) i--;
Some (including myself) would consider that using the ternary operator in this fashion is bad style. Just for fun, here's another way someone might write it that's also not very nice (also more likely to generate compiler warning):
i > 0 && i--;
In the end, style is a matter of preference. The compiler, for the most part, will decide the best way to turn your code into assembly. So you owe it to yourself to write code that is clear and concise.
I've inherited a sizeable codebase where someone, somehow, has written several conditionals like so:
enum
{
FOO_TYPE_A,
FOO_TYPE_B,
FOO_TYPE_C,
FOO_TYPE_D
};
void bar(int fooType)
{
if (fooType == FOO_TYPE_A || FOO_TYPE_B) // <-- This will always be true, since FOO_TYPE_B is nonzero!
{
// Do something intended for only type A or B
}
// Do things general to A,B,C,D
}
where the condition check should clearly be:
if (fooType == FOO_TYPE_A || fooType == FOO_TYPE_B)
Is there a warning in gcc I can turn on to find them all, similar to MSDN's C4127?
Specifically, I'm using the Android NDK r9d.
If not, why not? It seems like a useful catch-all for unintentional assignment, unsigned > 0 as well as the above foolishness.
EDIT: Made the code more verbose to illustrate the problem.
I do not see a warning that corresponds to MSDN C4127. GCC does have a warning that is somewhat similar in intent, but not to address your problem: -Wtype-limits
Warn if a comparison is always true or always false due to the
limited range of the data type, but do not warn for constant
expressions. For example, warn if an unsigned variable is compared
against zero with < or >=. This warning is also enabled by
-Wextra.
As you can see, GCC explicitly states it does not warn about constant expressions. The motivation for this may be due to the common use of constant expressions to leverage the compiler's dead code elimination so that macros (or portions of it) can be optimized away by using a compile time constant. It would be used as an alternative to conditional compilation (#if defined() and #if X == Y), as the macro reads more naturally like a regular function. As a hypothetical example:
#define VERIFY(E) \
do { \
if (NO_VERIFY) break; \
if (!(E) && (VERIFY_LOG_LEVEL >= log_level() || VERIFY_LOG_ALWAYS)) { \
log("validation error for: " #E); \
} \
} while (0)
I think the problem is that variable is a define or a const. CONSTANT_2 is a non-zero constant also make this problem.