Thank you all for your answers. I'm still somewhat confused about how in my example ap isn't sent by pointer to va_arg() but needs to be sent by pointer to the function calling va_arg() or something very bad might happen. Maybe my confusion stems from me thinking va_arg() is a function while it's actually a macro, which is very different now that I think about it.
Richard, I also tried mixing types up between int and long but couldn't get any incorrect or unexpected return from va_arg(). I tried to mishandle it by giving it incorrect types but didn't manage to break it.
Thank you for mentioning that stdarg.h and stdio.h are bad practice. I still need to use those as part of my C programming course but at least now I know not to use them moving forward.