MIPS is a really good way to learn all of this stuff, plus there are lots of resources. Usually all of the registers will be 32 bit wide on a 32 bit processor, once a 16 bit value is moved into a register it's usually padded with zeros. I'm speaking from a broad MIPS perspective here
Consider the following,
int x = 5, y = 10, r = 0;
r = x + y;
But how would "addi $t0, $0, 156" (add immediate) fit into 1 word you ask? (be it 32 bits or whatever). Thus any effort you went to to have a 'optimum' data type would go to waste (as shifting/padding must occur anyway). Of course 156 would have to be shifted to 32 bits to fit in a register / go in memory. Since,
lw $t0, x # load word...
lw $t1, y
add $t0, $t0, $t1
sw $t0, r # store word...
> Would it be more efficient to have a program that packs say 4 chars into a int, when it comes to loading from memory?
addi (6 bits) $t0 (5 bits -- 32 registers) $0 (5 bits -- again, 32 registers) 156 (only have 16 bits to represent immediate value)
Perhaps, but packing and unpacking is most likely going to be slower than going to memory 4 times... Not to mention the assembler will often pack itself (if memory is byte addressable).
I might be wrong... but hey, at least I'm adding more fuel to the fire. I'd suggest playing around with MIPS (ie a simulator MARS is good). Does wonders for learning.