Contenuti del Corso
C Preprocessing
C Preprocessing
Advanced Usage of Symbolic Constant
Let's consider practical examples of using macro substitutions.
Multi-Line Macro
The \
(backslash) character in macros is used to continue the macro definition to the next line.
main
#include <stdio.h> #define PRINT_SUM(a, b) \ int sum = (a) + (b); \ printf("Sum: %d\n", sum); int main() { PRINT_SUM(3, 5); // Call a macro that prints "Sum: 8" return 0; }
Code duplication
This code uses the #define macro to shorten and avoid duplication of the same fields in two structures (struct Product
and struct Customer
)
main
#include <stdio.h> #define COMMON_FIELDS \ int id; \ char name[50]; \ float price; // Declare the Product structure struct Product { COMMON_FIELDS // Using the macro char category[30]; }; // Declare the Customer structure struct Customer { COMMON_FIELDS // Using the macro char email[50]; char address[100]; }; int main() { struct Product p1 = {1, "Laptop", 999.99, "Electronics"}; struct Customer c1 = {2, "Alice", 0.0, "alice@example.com", "123 Main St"}; printf("Product: %s,\n Category: %s,\n Price: %.2f\n", p1.name, p1.category, p1.price); printf("Customer: %s,\n Email: %s,\n Address: %s\n", c1.name, c1.email, c1.address); return 0; }
Checking Logical Conditions
The macro automatically replaces the validation code without the need to write it manually and allows you to display useful information about the error.
main
#include <stdio.h> #define CHECK(condition) \ if (!(condition)) { \ printf("Error: %s not running!\n", #condition); \ } int main() { int x = 5; CHECK(x > 0); // Executes without error CHECK(x == 10); // Print an error message return 0; }
Logging
The LOG_LEVEL macro sets the logging level (LOG_WARNING). Only ERROR and WARNING level messages will be output, and INFO will be ignored.
main
#include <stdio.h> // Defining logging levels #define LOG_ERROR 1 // For critical errors #define LOG_WARNING 2 // For reporting potential problems #define LOG_INFO 3 // For general information about program execution #define LOG_LEVEL LOG_WARNING // Set the desired logging level void log_message(int level, const char *message) { if (level <= LOG_LEVEL) { // Condition for checking the logging level switch (level) { case LOG_ERROR: printf("ERROR: %s\n", message); break; case LOG_WARNING: printf("WARNING: %s\n", message); break; case LOG_INFO: printf("INFO: %s\n", message); break; default: break; } } } int main() { log_message(LOG_ERROR, "This is an error message"); log_message(LOG_WARNING, "This is a warning message"); log_message(LOG_INFO, "This is an info message"); return 0; }
Swipe to start coding
Add a new logging level.
- Set the logging level for
LOG_DEBUG
; - Set the desired logging level;
- Set a condition that checks whether a message should be output for a specific logging level;
- Specify the message text that will be displayed if the condition is not met.
Soluzione
Grazie per i tuoi commenti!
Advanced Usage of Symbolic Constant
Let's consider practical examples of using macro substitutions.
Multi-Line Macro
The \
(backslash) character in macros is used to continue the macro definition to the next line.
main
#include <stdio.h> #define PRINT_SUM(a, b) \ int sum = (a) + (b); \ printf("Sum: %d\n", sum); int main() { PRINT_SUM(3, 5); // Call a macro that prints "Sum: 8" return 0; }
Code duplication
This code uses the #define macro to shorten and avoid duplication of the same fields in two structures (struct Product
and struct Customer
)
main
#include <stdio.h> #define COMMON_FIELDS \ int id; \ char name[50]; \ float price; // Declare the Product structure struct Product { COMMON_FIELDS // Using the macro char category[30]; }; // Declare the Customer structure struct Customer { COMMON_FIELDS // Using the macro char email[50]; char address[100]; }; int main() { struct Product p1 = {1, "Laptop", 999.99, "Electronics"}; struct Customer c1 = {2, "Alice", 0.0, "alice@example.com", "123 Main St"}; printf("Product: %s,\n Category: %s,\n Price: %.2f\n", p1.name, p1.category, p1.price); printf("Customer: %s,\n Email: %s,\n Address: %s\n", c1.name, c1.email, c1.address); return 0; }
Checking Logical Conditions
The macro automatically replaces the validation code without the need to write it manually and allows you to display useful information about the error.
main
#include <stdio.h> #define CHECK(condition) \ if (!(condition)) { \ printf("Error: %s not running!\n", #condition); \ } int main() { int x = 5; CHECK(x > 0); // Executes without error CHECK(x == 10); // Print an error message return 0; }
Logging
The LOG_LEVEL macro sets the logging level (LOG_WARNING). Only ERROR and WARNING level messages will be output, and INFO will be ignored.
main
#include <stdio.h> // Defining logging levels #define LOG_ERROR 1 // For critical errors #define LOG_WARNING 2 // For reporting potential problems #define LOG_INFO 3 // For general information about program execution #define LOG_LEVEL LOG_WARNING // Set the desired logging level void log_message(int level, const char *message) { if (level <= LOG_LEVEL) { // Condition for checking the logging level switch (level) { case LOG_ERROR: printf("ERROR: %s\n", message); break; case LOG_WARNING: printf("WARNING: %s\n", message); break; case LOG_INFO: printf("INFO: %s\n", message); break; default: break; } } } int main() { log_message(LOG_ERROR, "This is an error message"); log_message(LOG_WARNING, "This is a warning message"); log_message(LOG_INFO, "This is an info message"); return 0; }
Swipe to start coding
Add a new logging level.
- Set the logging level for
LOG_DEBUG
; - Set the desired logging level;
- Set a condition that checks whether a message should be output for a specific logging level;
- Specify the message text that will be displayed if the condition is not met.
Soluzione
Grazie per i tuoi commenti!