If the required type and the given type are not compatible, you
have undefined behavior. It's entirely legal for a compiler to
pass type information with the value when passing a vararg, and
exploit it in va_arg
(although I don't know of any which do,
probably for historical reasons).
As for practical effects in your particular case, "%lu"
expects an unsigned long. The only other type which is
compatible is long, and then only if the actual value of the
long is non-negative. Passing it an int
is undefined
behavior, although it might work. (On most 32 bit platforms,
int
and long
have the same size and representation.)