I agree that on first sight these declarations look confusing. But once you know the idea behind them, things become easier. The main idea of C and C++ declarations was:
"Declare things the same way they are used"
So always start at the identifier and think of the entire construct as a regular C++ expression. Then resolve the expression by using the C++ precedence and associativity rules. Example:
Start at crack5. Peel off the first set of parentheses, as they do nothing. Then we have left:
The only thing we can do now is dereference the pointer operation. Hence crack5 is some kind of a pointer.
Then in the next step, the only thing we can do is perform a function call. Hence crack5 must be a pointer to a function.
Peel off one redundant set of parentheses again and we see that the function returns an int.
It takes some time to get used to this kind of reading a declaration. I would recommend you take a deeeeep look at the C++ precedence rules, as they are the key to all this.