Introduction to Constants
Constants in C are fixed values that cannot be changed during program execution. They provide a way to define values that remain the same throughout the program, improving code readability, maintainability, and reducing errors.
Types of Constants in C
Constants in C ├── Literal Constants │ ├── Integer Constants (10, -5, 0) │ ├── Floating-point Constants (3.14, 2.5e-3) │ ├── Character Constants ('A', '\n', '5') │ └── String Constants ("Hello", "C Programming") ├── Symbolic Constants │ ├── #define Preprocessor (PI, MAX_SIZE) │ └── const Keyword (const int MAX = 100) ├── Enumeration Constants (enum) └── Constant Expressions Literal Constants
Integer Constants
#include <stdio.h> int main() { // Decimal (base 10) int decimal = 42; // Octal (base 8) - starts with 0 int octal = 052; // 42 in decimal // Hexadecimal (base 16) - starts with 0x or 0X int hex1 = 0x2A; // 42 in decimal int hex2 = 0X2a; // 42 in decimal // Binary (C23 standard) - starts with 0b // int binary = 0b101010; // 42 in decimal (C23) // Integer suffixes long longVar = 42L; // long unsigned int uintVar = 42U; // unsigned int unsigned long ulVar = 42UL; // unsigned long long long llVar = 42LL; // long long printf("Decimal: %d\n", decimal); printf("Octal (052): %d\n", octal); printf("Hexadecimal (0x2A): %d\n", hex1); printf("Long: %ld\n", longVar); printf("Unsigned: %u\n", uintVar); printf("Long Long: %lld\n", llVar); return 0; } Output:
Decimal: 42 Octal (052): 42 Hexadecimal (0x2A): 42 Long: 42 Unsigned: 42 Long Long: 42
Floating-Point Constants
#include <stdio.h> int main() { // Decimal notation float f1 = 3.14159; double d1 = 2.71828; // Scientific notation double sci1 = 1.23e-4; // 0.000123 double sci2 = 5.67e+6; // 5670000 double sci3 = 8.9E2; // 890 // Hexadecimal floating-point (C99) double hex_float = 0x1.2p3; // (1 + 2/16) * 2^3 = 9.0 // Floating-point suffixes float floatVar = 3.14F; // float double doubleVar = 3.14; // double (default) long double ldVar = 3.14L; // long double printf("Pi: %f\n", f1); printf("e: %f\n", d1); printf("1.23e-4: %f\n", sci1); printf("5.67e+6: %f\n", sci2); printf("8.9E2: %f\n", sci3); printf("Hex float 0x1.2p3: %f\n", hex_float); printf("\nSizes:\n"); printf("float constant size: %zu bytes\n", sizeof(3.14F)); printf("double constant size: %zu bytes\n", sizeof(3.14)); printf("long double constant size: %zu bytes\n", sizeof(3.14L)); return 0; } Character Constants
#include <stdio.h> int main() { // Regular character char ch1 = 'A'; char ch2 = '5'; char ch3 = '$'; // Escape sequences char newline = '\n'; char tab = '\t'; char backspace = '\b'; char carriage = '\r'; char formfeed = '\f'; char backslash = '\\'; char single_quote = '\''; char double_quote = '\"'; char null_char = '\0'; // Octal and hexadecimal escape sequences char octal = '\101'; // 'A' in octal char hex = '\x41'; // 'A' in hexadecimal printf("Characters: %c %c %c\n", ch1, ch2, ch3); printf("Octal 101: %c\n", octal); printf("Hex 41: %c\n", hex); printf("Escape sequences:\n"); printf("Line 1%sLine 2\n", "\n"); // Newline printf("Column1\tColumn2\tColumn3\n"); // Tabs return 0; } String Constants
#include <stdio.h> int main() { // String literals char *str1 = "Hello, World!"; char str2[] = "C Programming"; // Multi-line string char *multi_line = "This is a " "multi-line " "string."; // String with escape sequences char *path = "C:\\Program Files\\MyApp"; char *message = "He said, \"Hello!\""; // Wide string (C99) wchar_t *wide_str = L"Wide string"; printf("str1: %s\n", str1); printf("str2: %s\n", str2); printf("multi_line: %s\n", multi_line); printf("path: %s\n", path); printf("message: %s\n", message); printf("\nString literal concatenation:\n"); printf("This " "is " "one " "string.\n"); return 0; } Symbolic Constants
Using #define Preprocessor
#include <stdio.h> // Simple constant definitions #define PI 3.14159 #define MAX_SIZE 100 #define NAME "C Programming" // Mathematical constants #define E 2.71828 #define GOLDEN_RATIO 1.61803 // Configuration constants #define BUFFER_SIZE 1024 #define TIMEOUT_MS 5000 #define DEBUG_MODE 1 // Bit masks #define FLAG_READ 0x01 #define FLAG_WRITE 0x02 #define FLAG_EXEC 0x04 // Macro-like constants (can have parameters) #define SQUARE(x) ((x) * (x)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) #define MIN(a,b) ((a) < (b) ? (a) : (b)) int main() { printf("PI: %f\n", PI); printf("MAX_SIZE: %d\n", MAX_SIZE); printf("NAME: %s\n", NAME); printf("E: %f\n", E); printf("\nBit masks:\n"); printf("FLAG_READ: 0x%02X\n", FLAG_READ); printf("FLAG_WRITE: 0x%02X\n", FLAG_WRITE); printf("FLAG_EXEC: 0x%02X\n", FLAG_EXEC); printf("\nMacros:\n"); printf("SQUARE(5): %d\n", SQUARE(5)); printf("MAX(10, 20): %d\n", MAX(10, 20)); printf("MIN(3.14, 2.72): %f\n", MIN(3.14, 2.72)); #ifdef DEBUG_MODE printf("\nDebug mode is ON\n"); #endif return 0; } Using const Keyword
#include <stdio.h> // Global constants const double PI = 3.141592653589793; const int MAX_USERS = 1000; const char* APP_NAME = "MyApplication"; // const with different types const int array[] = {1, 2, 3, 4, 5}; const float rates[] = {1.2, 2.3, 3.4, 4.5}; // Pointer to const const int* ptr_to_const; // pointer to constant int int* const const_ptr = NULL; // constant pointer to int const int* const const_ptr_to_const = NULL; // constant pointer to constant int int main() { // Local constants const int local_max = 50; const float tax_rate = 0.15; printf("PI: %f\n", PI); printf("MAX_USERS: %d\n", MAX_USERS); printf("APP_NAME: %s\n", APP_NAME); printf("local_max: %d\n", local_max); printf("tax_rate: %.2f\n", tax_rate); // Using const arrays printf("\nConst array: "); for (int i = 0; i < 5; i++) { printf("%d ", array[i]); } printf("\n"); // Cannot modify const variables // PI = 3.14; // Error! // local_max = 100; // Error! // array[0] = 10; // Error! // Demonstrating pointer to const int value = 42; ptr_to_const = &value; // *ptr_to_const = 100; // Error! Can't modify through pointer return 0; } const vs #define Comparison
#include <stdio.h> // #define - preprocessor, no type checking, no memory allocation #define MAX_SIZE 100 #define MULTIPLY(a,b) ((a)*(b)) // const - compiler, type checking, memory allocated const int max_size = 100; int main() { printf("=== #define vs const ===\n\n"); // #define advantages: // 1. No memory allocation // 2. Can be used in preprocessor directives printf("#define MAX_SIZE: %d\n", MAX_SIZE); printf("#define MULTIPLY(5,3): %d\n", MULTIPLY(5, 3)); // const advantages: // 1. Type checking // 2. Scope control // 3. Can be used with pointers printf("const max_size: %d\n", max_size); printf("Size of const variable: %zu bytes\n", sizeof(max_size)); // const with pointer const int *p = &max_size; printf("const pointer value: %d\n", *p); // #define limitations // #define VALUE 10 + 20 // int result = VALUE * 2; // 10 + 20 * 2 = 50, not 60 return 0; } Enumeration Constants
Basic Enum
#include <stdio.h> // Simple enum enum Weekday { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }; // Enum with explicit values enum Status { STATUS_OK = 0, STATUS_ERROR = -1, STATUS_NOT_FOUND = 404, STATUS_FORBIDDEN = 403 }; // Enum with bitmask values enum Permissions { PERM_NONE = 0, PERM_READ = 1 << 0, // 1 PERM_WRITE = 1 << 1, // 2 PERM_EXEC = 1 << 2, // 4 PERM_DELETE = 1 << 3, // 8 PERM_ALL = 15 }; int main() { enum Weekday today = WEDNESDAY; enum Status status = STATUS_OK; enum Permissions user_perm = PERM_READ | PERM_WRITE; printf("Today: %d (", today); switch (today) { case MONDAY: printf("Monday"); break; case TUESDAY: printf("Tuesday"); break; case WEDNESDAY: printf("Wednesday"); break; case THURSDAY: printf("Thursday"); break; case FRIDAY: printf("Friday"); break; case SATURDAY: printf("Saturday"); break; case SUNDAY: printf("Sunday"); break; } printf(")\n"); printf("Status: %d\n", status); printf("\nPermissions: %d\n", user_perm); if (user_perm & PERM_READ) printf(" Can read\n"); if (user_perm & PERM_WRITE) printf(" Can write\n"); if (user_perm & PERM_EXEC) printf(" Can execute\n"); if (user_perm & PERM_DELETE) printf(" Can delete\n"); return 0; } Typedef with Enum
#include <stdio.h> // Using typedef with enum typedef enum { COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_YELLOW, COLOR_CYAN, COLOR_MAGENTA } Color; typedef enum { LOG_LEVEL_DEBUG, LOG_LEVEL_INFO, LOG_LEVEL_WARNING, LOG_LEVEL_ERROR, LOG_LEVEL_FATAL } LogLevel; void log_message(LogLevel level, const char* message) { const char* level_names[] = { "DEBUG", "INFO", "WARNING", "ERROR", "FATAL" }; printf("[%s] %s\n", level_names[level], message); } int main() { Color bg = COLOR_BLUE; Color fg = COLOR_YELLOW; printf("Background color: %d\n", bg); printf("Foreground color: %d\n", fg); log_message(LOG_LEVEL_INFO, "Application started"); log_message(LOG_LEVEL_DEBUG, "Processing data"); log_message(LOG_LEVEL_WARNING, "Low disk space"); log_message(LOG_LEVEL_ERROR, "File not found"); log_message(LOG_LEVEL_FATAL, "Out of memory"); return 0; } Constant Expressions
Compile-Time Constants
#include <stdio.h> // Constant expressions - evaluated at compile time #define ARRAY_SIZE (5 * 4) // 20 #define BUFFER_SIZE (ARRAY_SIZE + 10) // 30 // constexpr (C23) - compile-time constant expressions // constexpr int MAX = 100; // C23 feature int main() { // Array size must be constant expression int array[ARRAY_SIZE]; char buffer[BUFFER_SIZE]; // sizeof is a compile-time constant const int int_size = sizeof(int); const int array_size = sizeof(array); printf("ARRAY_SIZE: %d\n", ARRAY_SIZE); printf("BUFFER_SIZE: %d\n", BUFFER_SIZE); printf("int_size: %d bytes\n", int_size); printf("array_size: %d bytes\n", array_size); printf("array elements: %d\n", (int)(sizeof(array) / sizeof(array[0]))); // Constant expressions can be used in case labels const int CASE_VALUE = 42; int value = 42; switch (value) { case CASE_VALUE: printf("Value matches constant expression\n"); break; default: printf("No match\n"); } return 0; } Constant Arrays and Strings
Constant Arrays
#include <stdio.h> // Global constant arrays const int days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; const char* month_names[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; // Constant 2D array const int multiplication_table[5][5] = { {1, 2, 3, 4, 5}, {2, 4, 6, 8, 10}, {3, 6, 9, 12, 15}, {4, 8, 12, 16, 20}, {5, 10, 15, 20, 25} }; int main() { printf("=== Months and Days ===\n"); for (int i = 0; i < 12; i++) { printf("%-10s: %2d days\n", month_names[i], days_in_month[i]); } printf("\n=== Multiplication Table ===\n"); for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { printf("%3d ", multiplication_table[i][j]); } printf("\n"); } return 0; } Constant Strings
#include <stdio.h> #include <string.h> // String constants const char* error_messages[] = { "Success", "File not found", "Permission denied", "Out of memory", "Invalid parameter", "Connection failed" }; const char* help_text = "Usage: program [options]\n" "Options:\n" " -h, --help Show this help\n" " -v, --version Show version\n" " -f, --file Input file\n"; int main() { printf("=== Error Messages ===\n"); for (int i = 0; i < 6; i++) { printf("Error %d: %s\n", i, error_messages[i]); } printf("\n=== Help Text ===\n"); printf("%s", help_text); // String literals are constant char *str1 = "Hello"; // Points to string literal (read-only) const char *str2 = "World"; // Better: explicit const // str1[0] = 'h'; // Undefined behavior! String literal may be read-only return 0; } Constant Pointers
Pointer to Constant vs Constant Pointer
#include <stdio.h> int main() { int a = 10, b = 20; int c = 30, d = 40; // 1. Pointer to constant int (data is constant) const int *p1 = &a; // *p1 = 100; // Error: can't modify through p1 p1 = &b; // OK: can change pointer // 2. Constant pointer to int (pointer is constant) int * const p2 = &c; *p2 = 300; // OK: can modify data // p2 = &d; // Error: can't change pointer // 3. Constant pointer to constant int (both constant) const int * const p3 = &a; // *p3 = 100; // Error: can't modify data // p3 = &b; // Error: can't change pointer printf("p1: %d (points to %d)\n", *p1, a); printf("p2: %d\n", *p2); printf("p3: %d\n", *p3); // Demonstrating usage in functions void print_array(const int *arr, int size) { for (int i = 0; i < size; i++) { printf("%d ", arr[i]); // Can read, but not modify } printf("\n"); } int numbers[] = {1, 2, 3, 4, 5}; print_array(numbers, 5); return 0; } Constant Parameters and Return Values
const in Functions
#include <stdio.h> #include <string.h> // const parameters int string_length(const char *str) { // str is a pointer to constant char // Can't modify the string content int len = 0; while (*str++) { len++; } return len; } // const in function that doesn't modify data void print_message(const char *msg) { printf("Message: %s\n", msg); } // Returning const pointer const char* get_error_message(int error_code) { static const char* errors[] = { "No error", "File error", "Memory error" }; if (error_code >= 0 && error_code < 3) { return errors[error_code]; } return "Unknown error"; } // Returning const data (by value) const int get_pi() { return 3; // Truncated, but const is meaningless for return by value } int main() { char str[] = "Hello, World!"; const char *msg = "Test message"; printf("Length of '%s': %d\n", str, string_length(str)); print_message(msg); const char *err = get_error_message(1); printf("Error: %s\n", err); // err[0] = 'X'; // Error: can't modify const data return 0; } Compound Literal Constants (C99)
#include <stdio.h> // Compound literals - create unnamed constants on the fly typedef struct { int x; int y; } Point; void print_point(const Point *p) { printf("(%d, %d)\n", p->x, p->y); } int main() { // Integer array compound literal int *arr = (int[]){1, 2, 3, 4, 5}; printf("Compound literal array: "); for (int i = 0; i < 5; i++) { printf("%d ", arr[i]); } printf("\n"); // Structure compound literal Point *p = &(Point){10, 20}; print_point(p); // Inline compound literal print_point(&(Point){30, 40}); // Array of structures Point *points = (Point[]){ {1, 1}, {2, 4}, {3, 9}, {4, 16} }; printf("\nPoints:\n"); for (int i = 0; i < 4; i++) { print_point(&points[i]); } return 0; } Constants in Header Files
constants.h
#ifndef CONSTANTS_H #define CONSTANTS_H // Mathematical constants #define PI 3.141592653589793 #define E 2.718281828459045 #define GOLDEN_RATIO 1.618033988749895 // Physical constants #define SPEED_OF_LIGHT 299792458.0 // m/s #define PLANCK_CONSTANT 6.62607015e-34 // J⋅s #define GRAVITATIONAL_CONSTANT 6.67430e-11 // m³/kg/s² // Application constants #define MAX_PATH_LENGTH 4096 #define MAX_BUFFER_SIZE 8192 #define DEFAULT_TIMEOUT 30 // seconds // Error codes typedef enum { ERR_SUCCESS = 0, ERR_NOT_FOUND = -1, ERR_PERMISSION = -2, ERR_INVALID_PARAM = -3, ERR_OUT_OF_MEMORY = -4 } ErrorCode; // Bit flags #define FLAG_NONE 0x00 #define FLAG_READ 0x01 #define FLAG_WRITE 0x02 #define FLAG_EXEC 0x04 #define FLAG_ALL 0x07 // Inline function (const-like behavior) static inline int min(int a, int b) { return a < b ? a : b; } static inline int max(int a, int b) { return a > b ? a : b; } #endif main.c
#include <stdio.h> #include "constants.h" int main() { printf("=== Mathematical Constants ===\n"); printf("PI: %.15f\n", PI); printf("E: %.15f\n", E); printf("Golden Ratio: %.15f\n", GOLDEN_RATIO); printf("\n=== Physical Constants ===\n"); printf("Speed of Light: %.0f m/s\n", SPEED_OF_LIGHT); printf("Planck Constant: %.2e J⋅s\n", PLANCK_CONSTANT); printf("\n=== Application Constants ===\n"); printf("Max Path Length: %d\n", MAX_PATH_LENGTH); printf("Default Timeout: %d seconds\n", DEFAULT_TIMEOUT); printf("\n=== Error Codes ===\n"); printf("ERR_SUCCESS: %d\n", ERR_SUCCESS); printf("ERR_NOT_FOUND: %d\n", ERR_NOT_FOUND); printf("\n=== Bit Flags ===\n"); printf("FLAG_READ: 0x%02X\n", FLAG_READ); printf("FLAG_WRITE: 0x%02X\n", FLAG_WRITE); printf("FLAG_EXEC: 0x%02X\n", FLAG_EXEC); printf("\n=== Inline Functions ===\n"); printf("min(10, 20): %d\n", min(10, 20)); printf("max(3.14, 2.72): %d\n", max(3.14, 2.72)); // Note: int version return 0; } Constant Comparison Table
| Type | Syntax | Evaluation | Type Safety | Memory | Scope |
|---|---|---|---|---|---|
| Literal | 42 | Compile-time | No | None | Any |
#define | #define MAX 100 | Preprocessor | No | None | Global |
const | const int max = 100; | Run-time | Yes | Yes | Block |
enum | enum {MAX=100}; | Compile-time | Limited | None | Global |
constexpr (C23) | constexpr int max = 100; | Compile-time | Yes | Maybe | Block |
Best Practices
Do's and Don'ts
// DO: Use const for values that shouldn't change const double PI = 3.14159; const int MAX_USERS = 1000; // DO: Use enum for related constants typedef enum { HTTP_OK = 200, HTTP_NOT_FOUND = 404, HTTP_ERROR = 500 } HttpStatus; // DO: Use const in function parameters void process_data(const int *data, size_t size); // DO: Use #define for preprocessor conditions #ifdef DEBUG #define LOG(msg) printf("DEBUG: %s\n", msg) #else #define LOG(msg) #endif // DO: Use compound literals for temporary constants draw_point(&(Point){10, 20}); // DON'T: Use magic numbers if (temperature > 32) { // What is 32? // ... } // DO: Use named constants const int FREEZING_POINT_F = 32; if (temperature > FREEZING_POINT_F) { // ... } // DON'T: Modify const variables (will cause errors) const int value = 10; // value = 20; // Error! // DON'T: Use #define for type-specific constants #define PI 3.14159 // OK, but consider const double // DON'T: Forget const for read-only parameters void bad_function(char *str) { // Should be const char* printf("%s\n", str); } // DO: Use const for read-only parameters void good_function(const char *str) { printf("%s\n", str); } Common Pitfalls
1. Modifying String Literals
#include <stdio.h> int main() { // BAD: Attempting to modify string literal char *str = "Hello"; // str[0] = 'h'; // Undefined behavior! May crash // GOOD: Use array for modifiable string char arr[] = "Hello"; arr[0] = 'h'; // OK printf("%s\n", arr); return 0; } 2. const and Pointers Confusion
#include <stdio.h> int main() { int x = 10, y = 20; // Confusing declarations const int *p1 = &x; // pointer to const int int const *p2 = &x; // same as above int * const p3 = &x; // const pointer to int const int * const p4 = &x; // const pointer to const int // *p1 = 100; // Error p1 = &y; // OK *p3 = 100; // OK // p3 = &y; // Error return 0; } 3. enum Size and Type
#include <stdio.h> enum Small { SMALL_VALUE = 255 // Fits in char }; enum Large { LARGE_VALUE = 100000 // May need int }; int main() { printf("Size of enum Small: %zu bytes\n", sizeof(enum Small)); printf("Size of enum Large: %zu bytes\n", sizeof(enum Large)); // enum underlying type is implementation-defined // Usually int, but can be smaller return 0; } Performance Considerations
#include <stdio.h> #include <time.h> #define LOOP_COUNT 10000000 int main() { clock_t start, end; // Using literal constant start = clock(); for (int i = 0; i < LOOP_COUNT; i++) { int x = 100; // Constant } end = clock(); printf("Literal constant: %ld ticks\n", end - start); // Using const variable const int VALUE = 100; start = clock(); for (int i = 0; i < LOOP_COUNT; i++) { int x = VALUE; // May be optimized } end = clock(); printf("const variable: %ld ticks\n", end - start); // Using #define #define DEF_VALUE 100 start = clock(); for (int i = 0; i < LOOP_COUNT; i++) { int x = DEF_VALUE; // Preprocessor substitution } end = clock(); printf("#define constant: %ld ticks\n", end - start); return 0; } Summary Table
| Constant Type | Example | Storage | Type Safety | Modifiable | Best Use |
|---|---|---|---|---|---|
| Integer literal | 42 | None | No | No | Quick values |
| Float literal | 3.14 | None | No | No | Math constants |
| Character literal | 'A' | None | No | No | Single chars |
| String literal | "Hello" | Static | No | No | Fixed messages |
#define | #define MAX 100 | None | No | No | Configuration |
const variable | const int x = 5; | Stack/Data | Yes | No | Local constants |
const global | const double PI; | Data | Yes | No | Global constants |
enum | enum {RED, GREEN}; | None | Limited | No | Related constants |
const array | const int arr[5]; | Data | Yes | No | Lookup tables |
const pointer | const int* p; | Stack | Yes | Pointer only | Function params |
Conclusion
Constants are fundamental to C programming:
Key Takeaways
- Literals are the simplest form of constants
#definecreates preprocessor constants (no type checking)constcreates typed constants (type checking, memory allocated)enumcreates a set of related integer constants- Constant pointers protect data from modification
- Compound literals create temporary constants
Choosing the Right Constant
- Use
constfor most constants (type safety) - Use
#definefor preprocessor conditions and simple values - Use
enumfor related sets of integer constants - Use literals for obvious, self-explanatory values
- Use compound literals for temporary structures
Benefits of Using Constants
- Readability: Named constants are self-documenting
- Maintainability: Change in one place
- Type safety: Compiler catches errors
- Optimization: Compiler can optimize better
- Prevents bugs: Can't accidentally modify
Constants make code more robust, maintainable, and self-documenting. They are essential for professional C programming.
https://macronepal.com/free-html-online-code-compiler/
https://macronepal.com/free-online-python-code-compiler/
https://macronepal.com/free-online-python2-code-compiler/
https://macronepal.com/free-online-java-code-compiler/
https://macronepal.com/free-online-javascript-code-compiler/
https://macronepal.com/free-online-node-js-code-compiler/
https://macronepal.com/free-online-c-code-compiler/
https://macronepal.com/free-online-c-code-compiler-2/
https://macronepal.com/free-online-c-code-compiler-3/
https://macronepal.com/free-online-php-code-compiler/
https://macronepal.com/free-online-ruby-code-compiler/
https://macronepal.com/free-online-perl-code-compiler/
https://macronepal.com/free-online-lua-code-compiler/
https://macronepal.com/free-online-tcl-code-compiler/
https://macronepal.com/free-online-groovy-code-compiler/
https://macronepal.com/free-online-j-shell-code-compiler/
https://macronepal.com/free-online-haskell-code-compiler/
https://macronepal.com/free-online-scala-code-compiler/
https://macronepal.com/free-online-common-lisp-code-compiler/
https://macronepal.com/free-online-d-code-compiler/
https://macronepal.com/free-online-ada-code-compiler/
https://macronepal.com/free-erlang-code-compiler/
https://macronepal.com/free-online-assembly-code-compiler/
