Reputation: 848
What is the usefulness of assert(), when we can also use printf and if-else statements will inform the user that b is 0?
#include <stdio.h>
#include <assert.h>
int main() {
int a, b;
printf("Input two integers to divide\n");
scanf("%d%d", &a, &b);
assert(b != 0);
printf("%d/%d = %.2f\n", a, b, a/(float)b);
return 0;
}
Upvotes: 3
Views: 185
Reputation: 33014
There're two things here that people conflate. Validation of run-time errors and compile-time bugs.
if
Say the user is supposed to enter only numbers, but the input encountered is alphanumeric then it's a run-time error; there's nothing that you, the programmer, can do about it. You've to raise this to the user in a user-friendly, graceful way; this involves bubbling up the error to the right layer, etc. There are multiple ways of doing this: returning error value, throwing an exception, etc. Not all options are available in all languages.
assert
On the other hand, there're design-time assumptions and invariants a programmer depends on when writing new code. Say you're authoring a function make_unit_vec
involving division of a vector’s components by its length. Passing the 0 vector breaks this function since it’ll lead to a divide-by-zero; an invalid operation. However, you don’t want to check this every time in this function, since you're sure none of the callers will pass the 0 vector -- an assumption, not about extern user input but, about internal systems within programmer’s control.
So the caller of this function should never pass a vector with length 0. What if some other programmer doesn’t know of this assumption and breaks make_unit_vec
by passing a 0 vector? To be sure this bug is caught, you put an assert i.e. you're asserting (validating) the design-time assumption you made.
When a debug build is run under the debugger, this assert will "fire" and you can check the call stack to find the erring function! However, beware that assertions don’t fire when running a release build. In our example, in a release build, the div-by-zero will happen, if the erroneous caller isn’t corrected.
This is the rationale behind assert
being enabled only for debug builds i.e. when NDEBUG
is not set.
Upvotes: 3
Reputation: 72855
Asserts are not used to inform users about anything. Assertions are used to enforce invariants in your program.
In the above program, the assert is misused. The b != 0
is not an invariant. It is a condition to be checked at runtime and the proper way to do it would be something like
if (b == 0) {
sprintf(stderr, "Can't divide by 0\n");
return -1;
}
This means that the program will check user input and then abort if it's incorrect. The assert would be inappropriate because, one, it can be compiled out using the NDEBUG
macro which will, in your case, alter program logic (if the input is 0, the program will continue to the printf with the NDEBUG
flag) and two because the purpose of an assert is to assert a condition at a point in the program.
The example in the wikipedia article I've linked to gives you a place where an assert is the right thing to use. It helps to ensure program correctness and improves readability when someone is trying to read and understand the algorithm.
Upvotes: 2
Reputation: 755114
That is not a good use of assert; validating user input with assert is too brutal for anything other than your own private use.
This is a better example — it is a convenient one I happen to have kicking around:
int Random_Integer(int lo, int hi)
{
int range = hi - lo + 1;
assert(range < RAND_MAX);
int max_r = RAND_MAX - (RAND_MAX % range);
int r;
while ((r = rand()) > max_r)
;
return (r % range + lo);
}
If the value of RAND_MAX
is smaller than the range of integers requested, this code is not going to work, so the assertion enforces that critical constrain.
Upvotes: 0
Reputation: 137960
It stops the program and prevents it from doing anything wrong (besides abruptly stopping).
It's like a baked-in breakpoint; the debugger will stop on it without the extra manual work of looking up the line number of the printf
and setting a breakpoint. (assert
will still helpfully print this information though.)
By default it's defined to be conditional on the NDEBUG
macro, which is usually set up to reflect the debug/release build switch in the development environment. This prevents it from decreasing performance or causing bloat for end users.
Note that assert
isn't designed to inform the user of anything; it's only for debugging output to the programmer.
Upvotes: 0
Reputation: 201537
assert will stop the program, it marks a condition that should never occur.
From Wikipedia,
When executed, if the expression is false (that is, compares equal to 0), assert() writes information about the call that failed on stderr and then calls abort(). The information it > writes to stderr includes:
the source filename (the predefined macro __FILE__)
the source line number (the predefined macro __LINE__)
the source function (the predefined identifier __func__) (added in C99)
the text of expression that evaluated to 0 [1]
Example output of a program compiled with gcc on Linux:
program: program.c:5: main: Assertion `a != 1' failed.
Abort (core dumped)
Upvotes: 0
Reputation: 6606
In your program if the condition b != 0
holds true then the program execution will continue otherwise it is terminated and an error message is displayed and this is not possible with printf
only. Using if-else
will work too but that is not a MACRO.
Upvotes: 0