cyberangles blog

Printing the Source Code of a C Program Itself

In the world of programming, there are often fascinating challenges that push the boundaries of what we think is possible. One such interesting concept is printing the source code of a C program within the program itself. This is not only a fun exercise but also a great way to understand how a program can access its own code, which has implications in areas like self - modifying code and debugging.

In this blog, we will explore different methods to achieve the goal of printing the source code of a C program, discuss common practices, best practices, and provide example usage.

2026-07

Table of Contents#

  1. Understanding the Problem
  2. Reading the Source File Directly
    • Common Practices
    • Example Usage
  3. Using Preprocessor Tricks
    • Common Practices
    • Example Usage
  4. Best Practices
  5. Conclusion
  6. References

1. Understanding the Problem#

The problem at hand is to print the source code of a C program from within the program itself. This might seem straightforward, but there are a few challenges. For instance, a program needs to know the location of its own source file, and it has to be able to read that file. Additionally, different operating systems may have different ways of handling file paths and permissions.

2. Reading the Source File Directly#

Common Practices#

  • Determine the Source File Path: In most cases, the source file is in the same directory as the executable. On Unix - like systems, you can use the __FILE__ preprocessor macro, which expands to the name of the current source file.
  • Open and Read the File: Use standard C file handling functions like fopen, fread, and fclose to open the source file, read its contents, and close the file respectively.

Example Usage#

#include <stdio.h>
 
int main() {
    FILE *file;
    char ch;
 
    // Open the source file for reading
    file = fopen(__FILE__, "r");
    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }
 
    // Read and print each character of the file
    while ((ch = fgetc(file)) != EOF) {
        putchar(ch);
    }
 
    // Close the file
    fclose(file);
 
    return 0;
}

In this example, the __FILE__ macro is used to get the name of the current source file. The file is then opened in read mode, and each character is read and printed until the end of the file is reached. Finally, the file is closed.

3. Using Preprocessor Tricks#

Common Practices#

  • Stringizing Macros: The preprocessor can be used to create a string representation of the source code. You can use the # operator to convert a macro argument into a string literal.
  • Multiple Macros: You can break the source code into smaller parts and use multiple macros to represent different sections of the code.

Example Usage#

#include <stdio.h>
 
#define CODE_SECTION_1 "#include <stdio.h>\n"
#define CODE_SECTION_2 "#define CODE_SECTION_1 \"#include <stdio.h>\\n\"\n"
#define CODE_SECTION_3 "#define CODE_SECTION_2 \"#define CODE_SECTION_1 \\\"#include <stdio.h>\\\\n\\\"\\n\"\n"
#define CODE_SECTION_4 "//... more code sections ...\n"
#define CODE_SECTION_5 "int main() {\n"
#define CODE_SECTION_6 "    printf(CODE_SECTION_1);\n"
#define CODE_SECTION_7 "    printf(CODE_SECTION_2);\n"
#define CODE_SECTION_8 "    printf(CODE_SECTION_3);\n"
#define CODE_SECTION_9 "    printf(CODE_SECTION_4);\n"
#define CODE_SECTION_10 "    printf(CODE_SECTION_5);\n"
#define CODE_SECTION_11 "    printf(CODE_SECTION_6);\n"
#define CODE_SECTION_12 "    printf(CODE_SECTION_7);\n"
#define CODE_SECTION_13 "    printf(CODE_SECTION_8);\n"
#define CODE_SECTION_14 "    printf(CODE_SECTION_9);\n"
#define CODE_SECTION_15 "    printf(CODE_SECTION_10);\n"
#define CODE_SECTION_16 "    printf(CODE_SECTION_11);\n"
#define CODE_SECTION_17 "    printf(CODE_SECTION_12);\n"
#define CODE_SECTION_18 "    printf(CODE_SECTION_13);\n"
#define CODE_SECTION_19 "    printf(CODE_SECTION_14);\n"
#define CODE_SECTION_20 "    printf(CODE_SECTION_15);\n"
#define CODE_SECTION_21 "    printf(CODE_SECTION_16);\n"
#define CODE_SECTION_22 "    printf(CODE_SECTION_17);\n"
#define CODE_SECTION_23 "    printf(CODE_SECTION_18);\n"
#define CODE_SECTION_24 "    printf(CODE_SECTION_19);\n"
#define CODE_SECTION_25 "    printf(CODE_SECTION_20);\n"
#define CODE_SECTION_26 "    printf(CODE_SECTION_21);\n"
#define CODE_SECTION_27 "    printf(CODE_SECTION_22);\n"
#define CODE_SECTION_28 "    printf(CODE_SECTION_23);\n"
#define CODE_SECTION_29 "    printf(CODE_SECTION_24);\n"
#define CODE_SECTION_30 "    printf(CODE_SECTION_25);\n"
#define CODE_SECTION_31 "    printf(CODE_SECTION_26);\n"
#define CODE_SECTION_32 "    printf(CODE_SECTION_27);\n"
#define CODE_SECTION_33 "    printf(CODE_SECTION_28);\n"
#define CODE_SECTION_34 "    printf(CODE_SECTION_29);\n"
#define CODE_SECTION_35 "    printf(CODE_SECTION_30);\n"
#define CODE_SECTION_36 "    printf(CODE_SECTION_31);\n"
#define CODE_SECTION_37 "    printf(CODE_SECTION_32);\n"
#define CODE_SECTION_38 "    printf(CODE_SECTION_33);\n"
#define CODE_SECTION_39 "    printf(CODE_SECTION_34);\n"
#define CODE_SECTION_40 "    printf(CODE_SECTION_35);\n"
#define CODE_SECTION_41 "    printf(CODE_SECTION_36);\n"
#define CODE_SECTION_42 "    printf(CODE_SECTION_37);\n"
#define CODE_SECTION_43 "    printf(CODE_SECTION_38);\n"
#define CODE_SECTION_44 "    printf(CODE_SECTION_39);\n"
#define CODE_SECTION_45 "    printf(CODE_SECTION_40);\n"
#define CODE_SECTION_46 "    printf(CODE_SECTION_41);\n"
#define CODE_SECTION_47 "    printf(CODE_SECTION_42);\n"
#define CODE_SECTION_48 "    printf(CODE_SECTION_43);\n"
#define CODE_SECTION_49 "    printf(CODE_SECTION_44);\n"
#define CODE_SECTION_50 "    printf(CODE_SECTION_45);\n"
#define CODE_SECTION_51 "    printf(CODE_SECTION_46);\n"
#define CODE_SECTION_52 "    printf(CODE_SECTION_47);\n"
#define CODE_SECTION_53 "    printf(CODE_SECTION_48);\n"
#define CODE_SECTION_54 "    printf(CODE_SECTION_49);\n"
#define CODE_SECTION_55 "    printf(CODE_SECTION_50);\n"
#define CODE_SECTION_56 "    printf(CODE_SECTION_51);\n"
#define CODE_SECTION_57 "    printf(CODE_SECTION_52);\n"
#define CODE_SECTION_58 "    printf(CODE_SECTION_53);\n"
#define CODE_SECTION_59 "    printf(CODE_SECTION_54);\n"
#define CODE_SECTION_60 "    printf(CODE_SECTION_55);\n"
#define CODE_SECTION_61 "    printf(CODE_SECTION_56);\n"
#define CODE_SECTION_62 "    printf(CODE_SECTION_57);\n"
#define CODE_SECTION_63 "    printf(CODE_SECTION_58);\n"
#define CODE_SECTION_64 "    printf(CODE_SECTION_59);\n"
#define CODE_SECTION_65 "    printf(CODE_SECTION_60);\n"
#define CODE_SECTION_66 "    printf(CODE_SECTION_61);\n"
#define CODE_SECTION_67 "    printf(CODE_SECTION_62);\n"
#define CODE_SECTION_68 "    printf(CODE_SECTION_63);\n"
#define CODE_SECTION_69 "    printf(CODE_SECTION_64);\n"
#define CODE_SECTION_70 "    printf(CODE_SECTION_65);\n"
#define CODE_SECTION_71 "    printf(CODE_SECTION_66);\n"
#define CODE_SECTION_72 "    printf(CODE_SECTION_67);\n"
#define CODE_SECTION_73 "    printf(CODE_SECTION_68);\n"
#define CODE_SECTION_74 "    printf(CODE_SECTION_69);\n"
#define CODE_SECTION_75 "    printf(CODE_SECTION_70);\n"
#define CODE_SECTION_76 "    printf(CODE_SECTION_71);\n"
#define CODE_SECTION_77 "    printf(CODE_SECTION_72);\n"
#define CODE_SECTION_78 "    printf(CODE_SECTION_73);\n"
#define CODE_SECTION_79 "    printf(CODE_SECTION_74);\n"
#define CODE_SECTION_80 "    printf(CODE_SECTION_75);\n"
#define CODE_SECTION_81 "    printf(CODE_SECTION_76);\n"
#define CODE_SECTION_82 "    printf(CODE_SECTION_77);\n"
#define CODE_SECTION_83 "    printf(CODE_SECTION_78);\n"
#define CODE_SECTION_84 "    printf(CODE_SECTION_79);\n"
#define CODE_SECTION_85 "    printf(CODE_SECTION_80);\n"
#define CODE_SECTION_86 "    printf(CODE_SECTION_81);\n"
#define CODE_SECTION_87 "    printf(CODE_SECTION_82);\n"
#define CODE_SECTION_88 "    printf(CODE_SECTION_83);\n"
#define CODE_SECTION_89 "    printf(CODE_SECTION_84);\n"
#define CODE_SECTION_90 "    printf(CODE_SECTION_85);\n"
#define CODE_SECTION_91 "    printf(CODE_SECTION_86);\n"
#define CODE_SECTION_92 "    printf(CODE_SECTION_87);\n"
#define CODE_SECTION_93 "    printf(CODE_SECTION_88);\n"
#define CODE_SECTION_94 "    printf(CODE_SECTION_89);\n"
#define CODE_SECTION_95 "    printf(CODE_SECTION_90);\n"
#define CODE_SECTION_96 "    printf(CODE_SECTION_91);\n"
#define CODE_SECTION_97 "    printf(CODE_SECTION_92);\n"
#define CODE_SECTION_98 "    printf(CODE_SECTION_93);\n"
#define CODE_SECTION_99 "    printf(CODE_SECTION_94);\n"
#define CODE_SECTION_100 "    return 0;\n}\n"
 
int main() {
    printf(CODE_SECTION_1);
    printf(CODE_SECTION_2);
    //... print all code sections ...
    printf(CODE_SECTION_100);
    return 0;
}

This method is more complex and requires a lot of manual work to break the code into sections and define the macros. However, it can be useful in situations where file access is restricted.

4. Best Practices#

  • Error Handling: Always check for errors when opening files. If the file cannot be opened, handle the error gracefully by printing an error message and returning an appropriate error code.
  • Portability: Make sure your code is portable across different operating systems. For example, the __FILE__ macro is a standard feature in C, but some operating systems may have different file path conventions.
  • Code Readability: If you use the preprocessor trick, try to keep the code as readable as possible. Break the code into logical sections and use meaningful macro names.

5. Conclusion#

Printing the source code of a C program itself is an interesting and challenging task. We have explored two different methods: reading the source file directly and using preprocessor tricks. Each method has its own advantages and disadvantages. Reading the source file directly is more straightforward but may face issues with file access. Using preprocessor tricks can be useful in restricted environments but requires more manual work.

By following the best practices, you can ensure that your code is robust, portable, and easy to understand.

6. References#

  • K&R C Programming Language, Second Edition
  • C Standard Library documentation
  • Online C programming tutorials and forums