The most convenient way is to probably to use a compiler builtin https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins..., if you want to be portable the next easiest way is to use a wide enough type (e.g. add or multiply two 32 bit numbers to a 64 bit one and verify it is inside [INT_MIN, INT_MAX]). Otherwise, you can either do a pre-condition check (for addition overflow occurs if a > 0 && b > 0 && a > INT_MAX-b || a < 0 && b < 0 && a < INT_MIN-b) or work with unsigned integers and check for wraparound after the operation. Finally, both clang and gcc have options to check for signed integer overflow at runtime (-fsanitize=signed-integer-overflow for gcc).
Of course, in practice this is too much effort for most people most of the time, so actual deployed C and C++ code is full of undefined behavior due to integer overflow. This paper has a great overview:
The overflow happens in the computation, you don't typically determine whether there was an overflow by checking the variable into which the result is saved (although perhaps this approach could work if you're using an unsigned integer type, which wraps around on overflow). You'd normally perform the check before you perform the addition (or whichever operation risks overflow). This can be fiddly to get right, but it's possible.
Also, the maximum value that can be represented in a variable of type uint32_t is (2^32) - 1, not 2^32.
Of course, in practice this is too much effort for most people most of the time, so actual deployed C and C++ code is full of undefined behavior due to integer overflow. This paper has a great overview:
https://wdtz.org/files/tosem15.pdf