Summary
1) #pragma
used for instruct the compiler to complete some specific actions;
#pragma
defined by many pointers are specific to the compiler
not portable between different compilers
preprocessor ignores
#pragma directives it does not recognize
- Different compilers may interpret the same #pragma directive in different ways
- General usage:
#pragma parameter
, different parameter parameters have different syntax and meanings.
2) #pragma message
and #warning, #pragma message only means a prompt message, not an error. (The three compilers of vc, bcc and gcc behave differently)
3) #pragma once
used for ensure that the header file is compiled only once;
#pragma once
is related to compiler and may not be supported. (Vc and gcc support, bcc does not support)
4) #ifndef...#define...#endif
can also be used to prevent header files from being included repeatedly. What is the difference #pragma once
#ifndef
method isC language and can be used in any compiler; if a
is included n times, the
pre-compiler will judge whether the header file has been included n times.
#pragma once
method is related tocompiler and may not be supported by all compilers; the
pre-compiler will only process it once, and will not judge it later.
5) What is memory alignment?
Different types of data are arranged in the memory according to certain rules,
not necessarily arranged one after another in order
6) Why is memory alignment required?
- The CPU's reading of the memory is not continuous, but
is read in blocks. The size of the block can only be a power
2, 1, 2, 4, 8... bytes
- When the data of the read operation is not aligned, it takes two
bus cycles to access the memory, so the performance of
will be greatly reduced
- Some hardware platforms can only read specific types of data from the specified relative address, otherwise a hardware exception will occur
7) The compiler is 4-byte alignment,
#pragma pack(n)
can adjust the default alignment of the compiler (vc and bcc compilers support 8-byte alignment, but gcc does not)
8) memory alignment rules:
·#Pragma analysis
#pragma
used for instruct the compiler to complete some specific actions;
#pragma
are compiler-specific, so not portable between different compilers
preprocessor ignores
#pragma directives it does not recognize
- Different compilers may interpret the same #pragma directive in different ways
- General usage:
#pragma parameter
, different parameter parameters have different syntax and meanings.
1、#pragma message
- The message parameter has similar implementations in most compilers
- The message parameter outputs a message to the compile output window at compile time
message is used to indicate the version information of the code in conditional compilation
#include <stdio.h> #if defined(ANDROID20) #pragma message("Compile Android SDK 2.0...") #define VERSION "ANDROID 2.0" #elif defined(ANDROID30) #pragma message("Compile Android SDK 3.0...") #define VERSION "Android 3.0" #elif defined(ANDROID40) #pragma message("Compile Android SDK 4.0...") #define VERSION "Amdroid 4.0" #else #error Compile version is not provided! #endif int main() { printf("%s\n", VERSION); return 0; }
不同编译器的编译结果: bcc编译器:bcc32 -DANDROID30 test.c 编译输出:Compile Android SDK 3.0... vc编译器:cl -DANDROID30 test.c 编译输出:Compile Android SDK 3.0... gcc编译器:gcc -DANDROID30 test.c 编译输出:note: #pragma message: Compile Android SDK 4.0... 三款编译器的输出说明:#pragma message会输出提示信息,但是行为相似,可能具体实现不同
单步编译的中间文件: gcc -DANDROID30 -E test.c -o test.i # 12 "test.c" #pragma message("Compile Android SDK 3.0...") # 12 "test.c" # 20 "test.c" int main() { printf("%s\n", "Android 3.0"); return 0; }
#warning, #pragma message 161cb1f7641a7a only represents a compilation message, not a program error.
2、#pragmae once
#pragma once
used forensure that the header file is only compiled once
#pragma once
is related tocompiler and may not be supported
#ifndef...#define...#endif
can also be used to prevent header files from being included repeatedly. What is the difference #pragma once
#ifndef
method isC language, which can be used in any compiler; if a
is included n times, the
pre-compiler will determine whether the header file has been included n times.
#pragma once
method is related tocompiler and may not be supported by all compilers; the
pre-compiler will only process it once, and will not be judged later.
// test.h #pragma once int aa = 1; // test.c #include <stdio.h> #include "test.h" #include "test.h" int main() { return 0; }
不同编译器的编译结果: bcc编译器:bcc32 test.c 编译输出:Variable 'aa' is initialized more than once vc编译器:cl test.c 编译输出:成功 gcc编译器:gcc test.c 编译输出:成功 分析:#pragma once预处理指示字,vc和gcc都可以识别,但是bcc就无法识别,直接忽略了,然后aa就会被定义2次,造成编译错误
Since #ifndef will be judged n times, but support #pragma once but not all compilers, in order to improve efficiency, both ways
simultaneously:
#ifndef _TEST_H_
#define _TEST_H_
#pragma once
// code
#endif
3. #pragma pack and memory alignment
3.1 What is memory alignment?
Different types of data are arranged in the memory according to certain rules,
not necessarily arranged one after another in order
3.2 Why do we need memory alignment?
- The CPU's reading of the memory is not continuous, but
is read in blocks. The block size can only be a power
2, 1, 2, 4, 8...bytes
- When the data of the read operation is not aligned, it takes two
bus cycles to access the memory, so the performance of
will be greatly reduced
- Some hardware platforms can only read specific types of data from the specified relative address, otherwise a hardware exception will occur
3.3 #pragma pack
compiler default alignment is 4-byte alignment
#pragama pack
can adjust the compiler's default alignment
#include <stdio.h> #pragma pack(1) struct Test1 { char c1; short s; char c2; int i; }; #pragma pack() #pragma pack(1) struct Test2 { char c1; char c2; short s; int i; }; #pragma pack() int main() { printf("sizeof(Test1) = %d\n", sizeof(struct Test1)); printf("sizeof(Test2) = %d\n", sizeof(struct Test2)); return 0; }
For the same two structs, after adjusting the memory alignment, the memory size occupied by Test1 has changed.
3.3 Rules of struct memory alignment:
- The first member starts at
0 offset
Each member is
alignment parameter (the
type size and the
pack parameter are smaller than
)
offset address must be divisible by
alignment parameter
(offset+size position of the previous member, offset address/alignment parameter == 0)
The type size of the structure type member
the data member with the largest internal length as its size
- The total length of struct must be an integer multiple of all alignment parameters of
#include <stdio.h>
#pragma pack(8)
struct Test1
{
short a;
long b;
};
struct Test2
{
char c;
struct Test1 st;
double d;
};
#pragma pack()
int main()
{
printf("sizeof(Test1) = %d\n", sizeof(struct Test1));
printf("sizeof(Test2) = %d\n", sizeof(struct Test2));
return 0;
}
不同编译器下的输出:
vc:8 和 24
gcc:8 和 20
bcc:8 和 24
Analysis: The output results of vc and bcc conform to our algorithm, why is the result of gcc different?
Answer: Many compiler directives of #pragma
defined by
not portable between different compilers.
gcc compiler does not support 8-byte alignment
and ignores'#pragma pack(8)' when it sees it. 161cb1f7641ef9 is still aligned with 4 bytes, and the result is 20:
struct Test2
{ pack offset memberSize
char c; 1 0 1
struct Test1 st; 4 4 8
double d; 4 12 8
} 总大小:20
This article is summarized from "C Language Advanced Course" by Tang Zuolin from "Ditai Software Academy".
If there are any errors or omissions, please correct me.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。