The library containing the printf and exit functions is a shared library (*.so) that is dynamically loaded after the program is started. The addresses of these functions are not known until the dynamic linker has placed the library in the address space of the process. The addresses can change from one run of the program to another.
You can use the gdb debugger to find where the dynamic linker has placed a function by running the program until a breakpoint, and then type p printf at the debugger prompt.
To avoid dynamic linking, you can link the libraries to your program statically. If you do this, the addresses are known beforehand, and can be examined using readelf. To compile a program statically using gcc, add the -static option to the command line, e.g.:
gcc -static myprog.c -o myprog