The pipe does not create command line arguments. Channel feeds standard input.
You need xargs convert standard input to command line arguments.
But you do not need (or want) xargs or ls or standard input here at all.
If you just want to compile each .c file into your own executable, just use:
gcc -o main *.c
(Normally, you do not need .h files on the gcc command line.)
As Kay points out in the comments, the pedantically correct and safe version of the aforementioned command (and I don't mean to derogate it):
gcc -o main ./*.c
See File names and path names in the shell: how to do this correctly for a detailed discussion of various problems here.
Having said that, you can use any of several tools to save you from having to do this and from having to rebuild everything when only a few things change.
Tools like make or its many clones, front-end (like autotools, cmake) or replacements (tup, scons, cons, and about a million other tools).
source share