&&
второй аргумент запускается только в том случае, если первый аргумент был успешным, т. е. если он завершился с кодом выхода 0. Код выхода 4 означает «сбой» для оболочки, поэтому echo
он не выполняется. Пытаться
gcc foo.c && ./a.out || echo $?
Если вы хотите увидеть код выхода только тогда, когда он не равен нулю. Если вы хотите видеть это всегда, используйте
gcc foo.c && ./a.out ; echo $?
Обратите внимание, что он может сообщить код выхода, gcc
если он не равен нулю.