The msg.sender
is always the address of the entity who called the current contract. When a contract calls another contract the msg.sender
changes. Let me give you some examples.
Assuming we have a EOA (Externally Owned Account) A and contracts B and C. When A calls B the msg.sender
in B is A's public address. If contract B also calls contract C, msg.sender
in contract C is B's (contract) address.
So the address of a user never changes (assuming he uses the same account) but the msg.sender
changes in contracts based on which entity initiated the call to that contract.
There is also tx.origin
which is always A in the aforementioned example (in every contract which is called in the transaction from A), but this should typically not be used.