These days, you'll see a LOT more code written in C and C++ than in Fortran, so I recommend C/C++. Since C++ is mostly a superset of C, I'd recommend learning that.
C++ has several features for doing elegantly and safely various things that must be done in ugly and bug-prone ways in plain C.
For deallocating memory that is no longer needed, one can create an object that allocates some memory, and then deallocates it in its destructor. That will keep the allocated memory from leaking. Memory leaks often result from a pointer going out of scope without its pointed-to memory getting deallocated. The Standard Template Library's containers use that technique.
One can do callbacks by defining virtual functions and then implementing them in subclasses.
For constants, one can use the "const" keyword instead of the preprocessor. It will automatically be type-safe, since its definition gives it a type.
#define UNLUCKY_NUMBER 13
const int UNLUCKY_NUMBER = 13;
Many functions defined with preprocessor macros can be expressed more safely with template functions.
#define MAX(x,y) ((x) >= (y))
template<class T> T &max(T &x, T &y) {return (x >= y) ? x : y;}
Operator overloading is useful if you wish to define some object that you wish to make behave in a numberlike fashion or an arraylike fashion or whatever.
If you wish to define a class of fractions, you can overload the familiar arithmetic and comparison operations to make one's fraction objects behave like integers and floats.
Etc.