Compiling and Running (with gcc)

A C program is written within a hello.c with code below. The main method is the entrypoint of the program, alongside sample ((constructor)) and ((destructor)).

  #include <stdio.h>

  __attribute__((constructor)) void init() {
    puts("pre hello world");
  }
  
  __attribute__((destructor)) void finish() {
    puts("post hello world");
  }
  
  int main() {
    puts("hello world");
    return 0;
  }
  

The program can be compiled into binary hello and ran. Further flags are often used to modulate the compilation step, see the provided reference table.

    gcc ./hello.c -o hello
    ./hello
  

Headers and Includes

Header files need to be included in C to declare symbols (function and type definitions, constants, macros) shared across multiple source files. Including tells the compiler about the symbols prior to use, allowing proper linkage, preventing undefined reference errors during compilation. Comes in 2 syntaxes, using the brackets or the quotes.

  1. #include <stdio.h>
    Brackets are used to include a pre-existing system header file, that are specified in the POSIX standard. The pre-processor uses the known system header location.
  2. #include "path/to/file.h"
    Quotes are used to to include a user-defined header file, by specifying a path relative to the C source file.
Essential gcc Flags
FlagDescription
-Wall Enable all common warnings
-Wextra Enable even more warnings
-Werror Treat warnings as errors (optional, strict mode)
-O2 Balance of optimization and compile speed
-g Include debug symbols (for gdb/lldb)
-std=c11 Use the C11 standard (or c17, c99 as needed)
-pedanticEnforce strict ISO C compliance

Binairies and Compiling in Docker Containers

After compiling a C program on the host machine, attempting to run it inside a docker container will likely fail. This is due to the differences of libc per distribution. To fix this issue, one option is to bypass the problem by copying the libc into the binary with gcc -static; another is to compile within the container:

    FROM alpine:3.21
    COPY ./hello.c .
    RUN apk add build-base && gcc hello.c -o hello
    ENTRYPOINT ["./hello"]