Problem
This example is a minimal reproduction of this issue encountered a code golf attempt. I am not advocating anyone use this style.
I am aware I may have hit undefined behaviour, my question is: why specifically, and does this go for C as well as C++?
I have this file:
#include <stdio.h>
int main() {
int a[]={1, 0}, i=0;
i += a[i]++;
printf("i=%d a=[%d, %d]\n", i, a[0], a[1]);
return 0;
}
With GCC on Ubuntu on WSL I get the expected i=1 a=[2, 0]
but with Visual C++ it is i=1 a=[1, 1]
The problem is fixed if I do this:
delta = a[i]++;
i += delta;
Whilst order of evaluation of assignment is unspecified, I am surprised that it appears that a[i]
is evaluated again for the increment, after the assignment of i
. The disassembly below seems to confirm this.
Do either the C or C++ standards allow this?
Background
Build command line and output on Windows:
>cl test.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.12.25830.2 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
test.c
Microsoft (R) Incremental Linker Version 14.12.25830.2
Copyright (C) Microsoft Corporation. All rights reserved.
/out:test.exe
test.obj
Dissasembly of the statement (built with /Zi
):
4: i += a[i]++;
00007FF6CBBA626C movsxd rax,dword ptr [i]
00007FF6CBBA6271 mov eax,dword ptr a[rax*4]
00007FF6CBBA6275 mov ecx,dword ptr [i]
00007FF6CBBA6279 add ecx,eax
00007FF6CBBA627B mov eax,ecx
00007FF6CBBA627D mov dword ptr [i],eax
00007FF6CBBA6281 movsxd rax,dword ptr [i]
00007FF6CBBA6286 mov eax,dword ptr a[rax*4]
00007FF6CBBA628A inc eax
00007FF6CBBA628C movsxd rcx,dword ptr [i]
00007FF6CBBA6291 mov dword ptr a[rcx*4],eax