En effet, lors du shifting des bits, il est important de s'assurer que les bits qui "dépassent" soient bien égaux à 0
Il n'y a pas de bits qui dépassent, un entier a toujours le même nombre de bits après un shift. Ce qui se passe dans ton code, c'est que le littéral 0xffffffff est un unsigned int, et que le & entre un int et un unsigned int renvoie un unsigned int. D'ailleurs avec un unsigned int j=0, un "|j" a le même effet (voir "conversions arithmétiques habituelles"). Le résultat de l'expression, un unsigned int, est ensuite imprimé comme un int.
Dans le premier code de Sarcadent, le problème est que l'opérateur << est susceptible de changer le signe, tandis que >> le conserve (voir "complément à deux").