1

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 is C 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 to compiler 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 for ensure that the header file is only compiled once
  • #pragma once is related to compiler 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 is C 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 to compiler 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.


bryson
169 声望12 粉丝