Asserts are a way of explicitly checking the assumptions that your code makes, which helps you track down lots of bugs by narrowing down what the possible problems could be. They are typically only evaluated in a special "debug" build of your application, so they won't slow down the final release version.
Let's say you wrote a function that took a pointer as an argument. There's a good chance that your code will assume that the pointer is non-NULL, so why not explicitly check that with an assertion? Here's how:
#include <assert.h>
void function(int* pointer_arg)
{
assert(pointer_arg != NULL);
...
}
An important thing to note is that the expressions you assert must never have side effects, since they won't be present in the release build. So never do something like this:
assert(a++ == 5);
Some people also like to add little messages into their assertions to help give them meaning. Since a string always evaulates to true, you could write this:
assert((a == 5) && "a has the wrong value!!");
Use assertions to check for "can't happen" situations.
Typical usage: check against invalid/impossible arguments at the top of a function.
Seldom seen, but still useful: loop invariants and postconditions.
Assertions are statements allowing you to test any assumptions you might have in your program. This is especially useful to document your program logic (preconditions and postconditions). Assertions that fail usually throw runtime errors, and are signs that something is VERY wrong with your program - your assertion failed because something you assumed to be true was not. The usual reasons are: there is a flaw in your function's logic, or the caller of your function passed you bad data.