C, unlike Java, uses different memory areas for different variables. So when you assign one struct to another, it does what is basically a shallow copy of one area to another. By shallow copy what I mean is that any pointers are not followed through to make clones of those so any pointers will point to the same place. It is just a copy of one memory area to another.
To say struct emp e2 = e1;
is the same thing as to say memcpy (&e2, &e1, sizeof(struct emp));
This in turn means that if you assign a struct to another struct variable and then modify the data in the other struct variable, the first struct variable is not modified.
So in C each variable is a different memory location where as with Java and some other languages you are working with variable references and the variable names are just containers for the variable reference (except for built in primitives like int).
You have a bit of a possible problem with your code in that you are using a constant string. It is not good to modify a constant string as you are doing with strupr() because you do not know how the memory is allocated or where it is allocated. So with doing a strupr() you are basically getting lucky.
See this about difference between a deep copy and a shallow copy.