grep -vl informaria o nome dos arquivos que possuem pelo menos uma linha que corresponde ao padrão. Aqui você quer os arquivos onde nenhum da linha corresponde ao padrão. O GNU grep (como encontrado no Debian) tem uma opção -L para isso:
grep -rlZ printf . | xargs -r0 grep -FL '#include <stdio.h>'
Com qualquer POSIX grep , você pode negar apenas grep -q :
find . -type f -exec grep -q printf {} \; \
! -exec grep -Fq '#include <stdio.h>' {} \; \
-print
Muito menos eficiente, pois isso significa executar duas instâncias grep em cada arquivo.