Originally Posted by
algorism
n = number < 0 ? number + 1u : number;
Mind you, that won't get you the twos-complement.
Originally Posted by
algorism
I think the difference is that with the if/else you specify the receiving variable separately for each assignment, but with the conditional operator you are assigning to the same variable.
I think that whiteflags maybe right. But you aren't off the mark either. I compared the assembly of the ternary and if statements in the following test code:
Code:
/* driver.c -- compile with -S and compare */
#include <stdio.h>
#include <limits.h>
int main(void)
{
int number = -1;
unsigned int n = (number < 0) ? UINT_MAX + number + 1 : number;
// unsigned int n;
// if (number < 0)
// n = UINT_MAX + number + 1;
// else
// n = number;
}
$ gcc -S driver.c
$ mv driver.c driver.c.ternary
// remove comments and comment ternary
$ gcc -S driver.c
This is the assembly for the ternary operation:
Code:
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $-1, -8(%rbp)
movl -8(%rbp), %eax
movl %eax, -4(%rbp)
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
And this is with the if statement:
Code:
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $-1, -8(%rbp)
cmpl $0, -8(%rbp)
jns .L2
movl -8(%rbp), %eax
movl %eax, -4(%rbp)
jmp .L3
.L2:
movl -8(%rbp), %eax
movl %eax, -4(%rbp)
.L3:
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
My assembly is rusty, but i think the answer is that in the if statement the code is explicitly comparing with cmpl to decide wether to jump, with jns (jump no sign).
The ternary operator on the other hand simplifies everything and doesn't even compare. The whole expression must have been first evaluated by the compiler and the final result translated (an optimization that I didn't ask and must be intrinsic to the operator).
The thing to keep in mind is that cmpl does a unsigned comparison. So, the comparison can be read as "cmpl $0, (unsigned)-8(%rbp)", or perhaps better, "if (unsigned)-8(%rbp) > $0 then jump", which is exactly what whiteflags was on about and I bet is precisely what gcc is doing during its evaluation of the ternary operator.