I posit that the code snippet below is probably as close as you're going to get with standard C and using logic operations to determine carry out and signed arithmetic overflow. This approach is an adaptation of how look ahead carry circuits are generated for arbitrary word lengths in FPGA's.
The basic sequence is to first determine which bit pairs will generate a carry and which will propagate a carry. In this presentation, the initial carry-in is presumed to be zero. A mask is marched along the "generate" and "propagate" words and with some logic and previous carry, determine carry to the next iteration. At the end of iteration, the carry flag will be set (or not) depending on the word pair bits to be added. The downside, is that this programming loop would be repeated every time you wanted to determine carry out and overflow for a given word pair - no such penalty in physical circuits or FPGA.
As a bonus, it's super easy to determine an overflow flag, which indicates whether the 2's compliment addition will be representable from the summation.
See the reference links below.
The code is for 32-bit integers, however could be adapted for longer or shorter types.
http://www.righto.com/2012/12/the-6502-overflow-flag-explained.html
https://en.wikipedia.org/wiki/Carry-lookahead_adder
// Global carry and overflow flags
// Set by carryLookahead()
bool carry, ov;
// Determines presence of carry out and overflow from 2's compliment addition
//
bool carryLookahead(int32 f1, int32 f2){
unsigned long mask;
unsigned long g,p;
unsigned char i;
// uses & sets global carry and ov flag variables
mask=1;
carry=ov=false; // initial carry and overflow flag assumed to be zero
g = f1 & f2; // bit pairs that will generate carry
p = f1 | f2; // bit pairs that will propagate a carry
for(i=0; i < 32; ++i, mask <<= 1){
ov=carry; // set ov to last carry
carry = (g&mask) || (p&mask) && carry; // use logical rather than bitwise logic to set the current carry;
ov=ov^carry; // ov is xor of last and current carries
}
return(carry);
}