In statically typed languages all type information is available at compile time, so the compiler won't have to figure out any type information at run-time. It knows what instructions to use by the type you give your variables. Dynamic (script) languages like JavaScript and Python obviously work differently as they don't have static types to rely on. In these languages the interpreter has to check what type different variables have before it does any work on them.
The easiest way to figure out this stuff is to look at the disassembly of the code the compiler generates. In Visual Studio (C++) you can do this by setting a breakpoint by the code you're curious about and when execution breaks there, press ALT+8. Not sure how other IDEs do this.
[COLOR=DimGray] int var1(1), var2(2);[/COLOR]
mov dword ptr [var1],1
mov dword ptr [var2],2
[COLOR=DimGray] int result1(var1 + var2);[/COLOR]
mov eax,dword ptr [var1]
add eax,dword ptr [var2]
mov dword ptr [result1],eax
As you can see, when working on ints all mov instructions operate on dwords (4 bytes). These values are moved from memory, into registers. The addition is done, and the result is moved back to memory.
[COLOR=DimGray] char var3(3), var4(4);[/COLOR]
mov byte ptr [var3],3
mov byte ptr [var4],4
[COLOR=DimGray] char result2(var3 + var4);[/COLOR]
movsx eax,byte ptr [var3]
movsx ecx,byte ptr [var4]
add eax,ecx
mov byte ptr [result2],al
The char code looks similar, but all mov instructions now operate on single byte pointers instead. Another difference is the movsx instruction, which in addition to working like a normal mov also converts the single byte var3 and var4 to 4-byte signed integers in the eax and ecx registers. Addition is then done on these 4-byte integers and the first byte of the result is put back in result2.