Click here to Skip to main content
15,887,683 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
C
int main ()
{
static int i=1;

printf("%d %d %d",i++,i,++i);

return 0;
}


What I have tried:

I have tried the same query using static
Posted
Updated 16-Sep-23 1:56am
v2
Comments
Richard MacCutchan 17-Sep-23 3:37am    
I just tried this in pure C and get the result 2 3 3, whether i is static or not. The take home message being: do not use expressions like this.
0x01AA 17-Sep-23 10:25am    
And I don't see a logic for that result :-)
Richard MacCutchan 17-Sep-23 10:37am    
In a C++ program it prints as 2 2 2. So there is no (real) logic in either case. The only way to see what is happening is by generating an assembler listing. I did discover a bug in the increment operator in the C compiler earlier this year, so this could be a manifestation of the same or a similar problem.
0x01AA 17-Sep-23 10:45am    
In c++ there is a 'logic'. The logic is to evaluate parameters from right to left. But of course, I would not rely on, that every compiler does it the same way.
Therefore, your statement 'The take home message being: do not use expressions like this.' is very ok but unfortunately I can't give you a five here for a comment ;)
Richard MacCutchan 17-Sep-23 11:14am    
See Solution 5.

Obviously the pre-increment is used first here. As 0x01AA has already noted, the result would otherwise be different. This kind of implementation is unreliable, but here the code and result make the question clear.

Why should the keyword static change the result here?
 
Share this answer
 
v2
Comments
0x01AA 16-Sep-23 9:24am    
My 5. And yes, 'static' does not (should never) have any effect.
Some information that may be of interest ... (or not, as the case may be)

1. The assembler generated by the C compiler

ASM
; 10   :     static int i=1;
; 11   : 
; 12   :     printf("%d %d %d",i++,i,++i);

	mov	eax, DWORD PTR ?i@?1??ctest@@9@9 ; eax = 1
	add	eax, 1                           ; eax = 2
	mov	DWORD PTR ?i@?1??ctest@@9@9, eax ; i = 2
	mov	ecx, DWORD PTR ?i@?1??ctest@@9@9 ; ecx = 2
	mov	DWORD PTR tv69[ebp], ecx         ; tv69 = 2
	mov	edx, DWORD PTR ?i@?1??ctest@@9@9 ; edx = 2
	add	edx, 1                           ; edx = 3
	mov	DWORD PTR ?i@?1??ctest@@9@9, edx ; i = 3
	mov	eax, DWORD PTR ?i@?1??ctest@@9@9 ; eax = 3
	push	eax                          ; push 3 -----> third value
	mov	ecx, DWORD PTR ?i@?1??ctest@@9@9 ; ecx = 3
	push	ecx                          ; push 3 -----> second value
	mov	edx, DWORD PTR tv69[ebp]         ; edx = 2
	push	edx                          ; push 2 -----> first value
	push	OFFSET $SG10501              ; push format string
	call	_printf



2. The assembler generated by the C++ compiler

ASM
; 18   :     static int i=1;
; 19   : 
; 20   :     printf("%d %d %d",i++,i,++i);

	mov	eax, DWORD PTR ?i@?1??CppTest@@YAHXZ@4HA ; eax = 1
	add	eax, 1                                   ; eax = 2
	mov	DWORD PTR ?i@?1??CppTest@@YAHXZ@4HA, eax ; i = 2
	mov	ecx, DWORD PTR ?i@?1??CppTest@@YAHXZ@4HA ; ecx = 2
	mov	DWORD PTR tv75[ebp], ecx                 ; tv75 = 2
	mov	edx, DWORD PTR ?i@?1??CppTest@@YAHXZ@4HA ; edx = 2
	mov	DWORD PTR tv73[ebp], edx                 ; tv73 = 2
	mov	eax, DWORD PTR ?i@?1??CppTest@@YAHXZ@4HA ; eax = 2
	mov	DWORD PTR tv69[ebp], eax                 ; tv69 = 2
	mov	ecx, DWORD PTR ?i@?1??CppTest@@YAHXZ@4HA ; ecx = 2
	add	ecx, 1                                   ; ecx = 3
	mov	DWORD PTR ?i@?1??CppTest@@YAHXZ@4HA, ecx ; i = 3
	mov	edx, DWORD PTR tv75[ebp]                 ; edx = 2
	push	edx                                  ; push 2 -----> third value
	mov	eax, DWORD PTR tv73[ebp]                 ; eax = 2
	push	eax                                  ; push 2 -----> second value
	mov	ecx, DWORD PTR tv69[ebp]                 ; ecx = 2
	push	ecx                                  ; push 2 -----> first value
	push	OFFSET $SG64299                      ; push format string
	call	_printf


Interestingly, if I remove the "-std:c++latest" option from the build
of the .cpp version, I get the result "2 3 3".
 
Share this answer
 
Comments
0x01AA 17-Sep-23 11:49am    
Great one, *thumbsup* and my 5
The printf evaluates/converts the parameter from left to right;
since the i++ is a post increment it is passed.
The i, nothing needs to be done.
Then the ++i is a pre increment so i is incremented then the printf prints 222.
 
Share this answer
 
Comments
0x01AA 16-Sep-23 7:01am    
You mean from right to left, right?
And I wouldn't rely on all compilers doing it this way. Altought it seems most do it ;)
Because prefix and postfix operators don't work like you think: Why Does x = ++x + x++ Give Me the Wrong Answer?[^]
 
Share this answer
 
Quote:
Why the output is 2 2 2 if I put static

You are in grey zone. This code is unpredictable and depends on compiler details and on optimizations, it can even change on different versions.
Never use a variable in a line of code with multiple increment/decrement of the variable. All you can predict is the value on next line of code.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900