#pragma / #error / #warning
| Since: | #pragma / #error | C89(1989) |
|---|---|---|
| #warning | C23(2023) |
These are supplementary preprocessor directives. #pragma controls compiler-specific behavior, #error forcibly stops compilation and displays a message, and #warning outputs a warning message.
Syntax
#pragma directive #pragma once #error error message #warning warning message #pragma pack(n) #pragma pack()
Common Directives
| Directive | Description |
|---|---|
| #pragma once | Tells the compiler to include the header file only once. Supported by most compilers, but is not part of the C standard. |
| #pragma pack(n) | Sets the member alignment of a structure to n-byte boundaries. Used to match structures with network protocols or external binary formats. |
| #pragma warning | Enables or disables specific warnings (supported by Visual C++, etc.). |
| #error | Stops compilation at the preprocessor stage and displays the specified message as an error. |
| #warning | Displays a warning message at the preprocessor stage. Compilation continues. Supported by GCC and Clang. |
Sample Code
sample_pragma_error.c
// Example: myheader.h
// Use #pragma once for a concise header guard.
#pragma once
#define MY_HEADER_DEFINED
// Check the C standard version and control compilation accordingly.
#if __STDC_VERSION__ < 199901L
#error "This code requires C99 or later."
#endif
// Warn about a feature planned for removal (GCC / Clang).
// #warning "This function is deprecated. Use new_func() instead."
sample_pragma_error.c
// Example: main.c
#include <stdio.h>
// Lay out the structure in memory without padding (example: network packet).
#pragma pack(1)
typedef struct {
unsigned char type; // 1 byte
unsigned short length; // 2 bytes (no padding)
unsigned int data; // 4 bytes
} PacketHeader;
#pragma pack() // Restore default alignment.
// Compare with a padded structure.
typedef struct {
unsigned char type;
unsigned short length;
unsigned int data;
} PacketHeaderPadded;
int main(void) {
printf("Size with pack(1): %zu bytes\n", sizeof(PacketHeader));
// Prints "7" (no padding).
printf("Normal size: %zu bytes\n", sizeof(PacketHeaderPadded));
// May be 8 or more depending on the environment, due to alignment.
return 0;
}
Common Mistakes
Common Mistake: Not Resetting #pragma pack
If you set #pragma pack(1) and don't reset it with pack(), the no-padding rule applies to all subsequent structs as well.
#include <stdio.h>
/* NG: not resetting pack(1) affects all subsequent structs */
#pragma pack(1)
typedef struct { unsigned char a; int b; } Packed;
/* This struct is also affected by pack(1) */
typedef struct { char x; double y; } AlsoAffected;
int main(void) {
printf("Packed: %zu\n", sizeof(Packed)); /* 5 bytes */
printf("AlsoAffected: %zu\n", sizeof(AlsoAffected)); /* 9 bytes (normally 16) */
return 0;
}
pragma_pack_ok.c
#include <stdio.h>
#pragma pack(1)
typedef struct { unsigned char a; int b; } Packed;
#pragma pack() /* OK: always reset afterwards */
typedef struct { char x; double y; } Normal;
int main(void) {
printf("Packed: %zu\n", sizeof(Packed)); /* 5 bytes */
printf("Normal: %zu\n", sizeof(Normal)); /* normal alignment (e.g. 16 bytes) */
return 0;
}
Run the following command:
gcc pragma_pack_ok.c -o pragma_pack_ok ./pragma_pack_ok Packed: 5 Normal: 16
Notes
The C standard specifies that #pragma directives unknown to the compiler must be ignored. As a result, the directives supported by each compiler vary. #pragma pack changes the memory layout of structures, so misuse can cause alignment violations, leading to performance degradation or crashes. Limit its use to specific purposes such as network packets.
#error is useful for enforcing required preconditions — such as the C standard version, specific macro definitions, or the target architecture. Combined with conditional compilation, it lets you catch incorrect build environments early.
For more on conditional compilation, see #ifdef / #ifndef / #endif. For macro definitions, see #include / #define (constants).
If you find any errors or copyright issues, please contact us.