PIDs should be stored in a variable of type pid_t.
Any memory that you read/write from multiple processes (or threads) must be protected either by some sort of mutex or by atomic operations with an appropriate memory order. It would not be enough to volatile.
PIDs should be stored in a variable of type pid_tEdit: It does indeed happen. Looking at the relevant assembly (at -O3):
# *flag = 1;
400840: mov DWORD PTR [r12],0x1
# child_pid = fork();
400848: call 400720 <fork@plt>
40084d: mov esi,0x4009c0
400852: mov r14d,eax
400855: mov edi,0x2
# signal(SIGINT, intHandler); - oh, this should be before the fork!
40085a: call 4006c0 <__sysv_signal@plt>
# 3-way branch for child_pid
40085f: test r14d,r14d
400862: js 400885 <main+0x155>
400864: je 400897 <main+0x167>
# child_pid > 0
400866: mov edx,DWORD PTR [r12]
# if (*flag) - condition only tested once
40086a: test edx,edx
40086c: je 400870 <main+0x140>
# infinite loop
40086e: jmp 40086e <main+0x13e>
# else
400870: mov esi,DWORD PTR [r13+0x0]
400874: mov edi,0x400af2
400879: xor eax,eax
# printf("The sum is: %d\n", *sum);
40087b: call 400680 <printf@plt>
400880: jmp 400772 <main+0x42>
# child_pid < 0
400885: mov edi,0x400ae5
# printf("Fork error. \n");
40088a: call 400660 <puts@plt>
40088f: or edi,0xffffffff
# exit(-1); - should use 1 or EXIT_FAILURE actually.
400892: call 400710 <exit@plt>
# child_pid == 0
400897: mov edi,0x2
40089c: mov esi,0x1
# signal(SIGINT, SIG_IGN); //ignore ctrl+c
4008a1: call 4006c0 <__sysv_signal@plt>
4008a6: mov eax,DWORD PTR [rbx]
4008a8: add eax,DWORD PTR [rbp+0x0]
4008ab: xor edi,edi
# *sum = *num1 + *num2;
4008ad: mov DWORD PTR [r13+0x0],eax
# *flag = 0;
4008b1: mov DWORD PTR [r12],0x0
# exit(0);
4008b9: call 400710 <exit@plt>