I was told in an interview that, in C, using the ++ operator (say i++) is an atomic operation while doing, say "i += 1" is not. I thought these operations were exactly the same when it comes to thread safety or atomicity. Am I missing something or are these actually different?
-
10The interviewer is wrong - neither are guaranteed to be atomic. – Paul R Jan 16 '15 at 04:10
-
4If a potential future boss told you that, I suggest you find another place of potential employment. – WhozCraig Jan 16 '15 at 04:17
-
3The compiler is likely to implement the expressions `++i` and `i += 1` very similarly (they're the same because the result of the expression is the incremented value). This is different from `i++` where the result of the expression is the value before the increment. As full statements, the three are equivalent. None of them is guaranteed to be atomic. – Jonathan Leffler Jan 16 '15 at 04:18
-
1See also [In C, is `i += 1` atomic?](http://stackoverflow.com/questions/1790204/in-c-is-i-1-atomic) It is not a duplicate because it doesn't mention `i++` or `++i`, but it is closely related. – Jonathan Leffler Jan 16 '15 at 04:22
-
This is a very good example of why C++ != C. +1.on your question (be sure to give a -1 on your examiner. Unless you need the job ;)). – frasnian Jan 16 '15 at 04:50
3 Answers
It's nonsense. Either one may or may not be atomic, depending on the data type, the architecture, and perhaps the compiler (the standard doesn't make guarantees about atomicity in general unless you're using C11 atomics), but I can't see any good reason to think that, in general, i++
would be atomic where i += 1
isn't. It's very likely that they actually generate the same code, in a context where the result of the expression isn't used.

- 223,387
- 19
- 210
- 288
The statements* i++;
and i += 1;
are equivalent in C. Neither is guaranteed to be atomic.
In particular, increments of variables larger than the system word size (e.g, 64-bit variables on 32-bit systems) are almost always non-atomic, as incrementing such a variable atomically would often require explicit locking. Additionally, some architectures do not support directly incrementing variables in memory. (That is, they require an explicit load/modify/store sequence.) These architectures cannot atomically modify any variable without locking.
* when considered as standalone statements, not expressions

- 65,258
- 11
- 75
- 141
the interviewer is wrong.
I compiled two function with gcc-4.8.2 -O2
-S
void increment1(int *a) {
*a += 1;
}
void increment2(int *a) {
(*a)++;
}
both generate exactly the same
assembly
increment1:
.LFB0:
.cfi_startproc
addl $1, (%rdi)
ret
.cfi_endproc
.LFE0:
.size increment1, .-increment1
.p2align 4,,15
.globl increment2
.type increment2, @function
increment2:
.LFB1:
.cfi_startproc
addl $1, (%rdi)
ret
.cfi_endproc
But in the context in more exact technical tarm, both of them are atomic write
which means it does not provide MAD result.
if you use int64_t variable in 32 or less bit-wise CPU environment, 64bit-wise modification cause multiple write operation. It cannot be atomic write
without lock.
You can use __sync_fetch_and_add(&a, 1)
operation for atomic increment in gcc environment.

- 389
- 1
- 5
-
2Just because these two functions generate identical x86 assembly using this version of GCC doesn't necessarily mean that they're **always** identical. Different compilers and architectures may behave differently. (You're correct here that they're identical, but only by accident.) – Jan 16 '15 at 04:32