It can be made even simpler, by arranging for **the C program** to remove itself when it runs:

    #! /bin/bash
    
    # Create a temporary file name for the executable file:
    TMP_PROGRAM_FILE="$(mktemp programXXXXXX)"
    
    # Compile the embedded C program:
    gcc -o "$TMP_PROGRAM_FILE" -x c - <<- END_OF_SOURCE
    #include <stdio.h>
    #include <unistd.h>
    
    int main(int argc, char* argv[]) 
    {
        int i;
    
        puts("Hello, world! I am a pseudoportable C program.");
        for (i = 1; i < argc; ++i) 
        {
            printf("Argument %d: %s\n", i, argv[i]);
        }
        unlink("$TMP_PROGRAM_FILE");
        return argc - 1;
    }
    END_OF_SOURCE
    
    # Run the program delegating all the arguments:
    ./$TMP_PROGRAM_FILE $@

This will not work under Windows but does work under Linux.  I haven't tested Mac, but believe it will work there, too. The change, of course, is that the C program now deletes itself.