Usage of #pragma in Linux

Usage of precompiled directive #pragma

Original: https://blog.csdn.net/tigerjibo/article/details/7000861 

When looking at the code in an open source project recently, I found that #pragma programs are used in many places. Therefore, I asked the Google teacher and summarized the common usage of #pragma precompiled instructions. Now I will share with you.

1. #pragma the most commonly used method

1. #progma pack(n)

1>Function:

Use the #progma pack precompilation directive to change the default value of the compiler (not absolute, some compilers can only use fixed data alignment).

2>Description

In most cases, we do not consider alignment issues when we write programs, because the compiler will choose the right strategy for us. Most compilers use four-byte alignment by default.

You can see a program to understand:

Procedure A:

#include<stdio.h>

struct  A

{

    int       a;

    char     b;

    short    c;   

};

int main ()

{

    int d;

    d=  sizeof (struct A);

    printf(“theleng=%d\n”,d);

     return 0;

}

Note:

(1) Generally, we are using 32-bit processors, and the default alignment byte number of the vc compiler is 4 bytes. Under gcc, by default, the largest type of variable in the structure is byte-aligned.

Structure A contains an int with a length of 4 bytes, a char with a length of 1 byte, and a short data with a length of 2 bytes. So the space used by A should be 7 bytes. But because the compiler needs to align the data members in space. So use the sizeof(strcut A) value of 8 "a occupies 4 bytes, b occupies one byte, and c occupies two bytes, so the compiler will put b and C in one 4 bytes, so the structure Body A occupies 8 bytes"

(2) Now we discuss the benefits of byte alignment:

The memory space in modern computers is divided according to bytes. In theory, it seems that access to any type of variable can start from any address, but the actual situation is that when accessing a specific variable, it is often accessed at a specific memory address. This All types of data need to be arranged in space according to certain rules, instead of being arranged one after another in order, this is alignment

 

The role and reason of alignment: The processing of storage space by various hardware platforms is very different. Some platforms can only access certain types of data from certain specific addresses. Other platforms may not have this situation, but the most common is that if the data storage is not aligned according to the requirements of the platform, it will cause a loss in access efficiency

 

For example, some platforms start with an even address every time. If an int type (assuming a 32-bit system) is stored at the beginning of the even address, then a read cycle can be read, and if it is stored at the odd address In some places, it may take 2 read cycles and piece together the high and low bytes of the two read results to get the int data. Obviously, the reading efficiency has dropped a lot. This is also a game between space and time

3>How to Use?

Examples of usage:
#pragma pack(push) //Save the previous alignment state, push is to push the previous alignment state onto the stack  
#pragma pack(1) //Specify the new alignment state, 1 byte
//define you The structure of  
//…………  
#pragma pack(pop) //Pop the stack and restore the previous alignment state

Now we modify the program just now:

Procedure B:

#include<stdio.h>

 

#pragma   pack(push)

#pragma pack (1)

 

struct  A

{

    int       a;

    char     b;

    short     c;   

};

#pragma     pack(pop);

int main ()

{

    int  d;

    d =  sizeof (struct A);

    printf(“theleng=%d\n”,d);

     return 0;

}

At this time, because it is aligned by one byte, structure A occupies a total of 7 bytes.

2. #pragma message("string constant")

1>Function:

When the compiler encounters this instruction, it prints the message text in the compile output window

2>Description:

When we define many macros in the program to control the source code version, we may forget whether we have set these macros correctly. At this time, we can use this instruction to check when compiling.

3>How  to  use?
#pragma message(“macro activated!”)

Note: There is no semicolon after message() here.

3.#pragma  once

1>Function:

Just add this instruction at the very beginning of the header file to ensure that the header file is compiled once

2>Note: The difference between #pragma once and #ifndef

(1) Similarities:

In order to avoid the same file being included multiple times, there is not much difference between #ifndef mode and #pragma once mode (provided that the compiler can support both modes at the same time).

(2) How to use both:

method one:

#ifndef  __TIGER_H__

#define  __TIGER_H__

……….//Some declaration statements

#endif

Method Two:

#pragma   once

………//Some declaration statements

(3) The difference between the two:

The method of #ifndef relies on the fact that the macro names cannot conflict. This not only ensures that the same file will not be included multiple times, but also that two header files with the same content will not be accidentally included at the same time. Of course, the disadvantage is that if the macro names of different header files accidentally "crash", it may cause the header files to exist, but the compiler insists that the declaration cannot be found.

#pragma once is guaranteed by the compiler: the same file will not be included multiple times. Note that the same file mentioned here refers to one physical file, not two files with the same content. The advantage is that you don't have to think about a macro name anymore, and of course there will be no strange problems caused by macro name collisions. The corresponding disadvantage is that if there are multiple copies of a header file, this method cannot guarantee that they will not be included repeatedly. Of course, compared to the "cannot find declaration" problem caused by macro name collisions, repeated inclusions are easier to find and correct.

For #pragmaonce, according to MSDN, it can prevent a file from being included multiple times. Compared with file protection in the form of #ifndef #define #endif, the former is platform-dependent and has poor portability, but it is more efficient because it does not need to open the included file to determine whether the file has been contain. Of course, this work is done for us by the system. The advantage of the latter is that it is a language-related feature, so portability is good. But when including a file, only open the file, and judge whether the file has been included according to whether the protection macro of the file has been defined. The efficiency is relatively low. Of course, when #include, the programmer can also judge whether the protection macro of the file to be included has been defined, to decide whether to include the file. Similar to the following code:

#ifndef FILE_H_

#include "file.h"

#endif

This can get higher efficiency and ensure portability. However, the dependence between files is high. If the protection macro of a file is changed, all files containing this file in the above format must be modified. Contrary to the idea of ​​modularity.

2. #pragma some other methods

1. The #pragma parameter is code_seg.

1>Format: 

#pragma code_seg( [ [ { push | pop}, ] [ identifier, ]] [ "segment-name" [, "segment-class" ] )

2>Function:

It can set the code segment of the function code in the program, which will be used when we develop the driver

3>Description:

This command is used to specify the section where the function is stored in the .obj file. To observe the OBJ file, you can use the dumpbin command line program that comes with VC. The default storage section of the function in the .obj file is the .text section, if code_seg does not take parameters. , The function is stored in the .text section. push (optional parameter) Put a record on the stack of the internal compiler. The optional parameter can be an identifier or a section name. pop (optional parameter) Pop a record from the top of the stack. The record can be an identifier or a section name. identifier (optional parameter) When the push instruction is used, an identifier is assigned to the record pushed onto the stack. When the identifier is deleted, the record in the stack associated with it will be popped from the stack. "segment-name" (optional parameter) represents the name of the section where the function is stored

3>Example:

//By default, functions are stored in the .text section

void func1() {                  // stored in .text

}

 

//Store the function in the .my_data1 section

#pragma code_seg(".my_data1")

void func2() {                  // stored in my_data1

}

 

//r1 is the identifier, put the function in the .my_data2 section

#pragma code_seg(push, r1, ".my_data2")

void func3() {                  // stored in my_data2

}

 

int main () {

}

2. # pragma hdrstop

1>Function:

Indicates that the precompiled header file ends here, the following header files are not precompiled, BCB can precompile the header files to speed up the link, but if all header files are precompiled, it may take up too much disk space, so use this Option to exclude some header files. 

Sometimes there are dependencies between units, for example, unit A depends on unit B, so unit B must be compiled before unit A. You can use #pragma startup to specify the compilation priority. If #pragma package(smart_init) is used, BCB will be compiled according to the priority. 
3. #pragma warning

1>Function:

This directive allows to selectively modify the behavior of compiler warning messages

2>Command format:

#pragma warning( warning-specifier :warning-number-list [; warning-specifier : warning-number-list...]

#pragma warning( push[ ,n ] )

#pragma warning( pop )

3>The main warnings used are as follows:

once: Only display the message once (warning/error, etc.)

default: reset the warning behavior of the compiler to the default state

1,2,3,4: Four warning levels

disable: prohibit the specified warning message

error: report the specified warning message as an error

If you don't understand the above explanation very well, you can refer to the following example and explanation

#pragma warning( disable : 4507 34; once : 4385; error: 164 ) 

Equivalent to: 

#pragma warning(disable:4507 34) // Do not display warning messages 4507 and 34 

#pragma warning(once:4385) // Warning message No. 4385 is only reported once 

#pragma warning(error:164) // Regard warning message 164 as an error. 

At the same time, this pragma warning also supports the following format: 

#pragma warning( push [ ,n ] ) 

#pragma warning( pop ) 

Here n represents a warning level (1---4). 

#pragma warning( push) Save the existing warning status of all warning messages. 

#pragma warning( push, n) save the existing warning status of all warning messages, and put the global warning 

The level is set to n.  

#pragma warning( pop) Pops the last warning message to the stack, which is done between stacking and popping 

All changes are cancelled. E.g: 

#pragma warning( push ) 

#pragma warning( disable : 4705 ) 

#pragma warning( disable : 4706 ) 

#pragma warning( disable : 4707 ) 

#pragma warning( pop )

At the end of this code, save all warning messages (including 4705, 4706 and 4707)

When using standard C++ for programming, you often get a lot of warning messages, and these warning messages are unnecessary prompts.

So we can use #pragma warning(disable:4786) to disable this type of warning

When using ADO in vc, you will also get unnecessary warning messages. At this time, we can pass

#pragma warning(disable:4146) to eliminate this type of warning message

4. # pragma comment (...)

1>Function:

This instruction puts a comment record into an object file or executable file.

2>Format:

#pragma comment( "comment-type" [,commentstring] )

comment-type: Can be specified as one of five predefined identifiers

The five predefined identifiers are:

(1) compiler: Put the version number and name of the compiler into the target file, this comment record will be ignored by the compiler, if you provide the commentstring parameter for the record type, the compiler will generate a warning

For example: #pragma comment( compiler)

(2) exestr: Put the commentstring parameter into the target file, this string will be put into the executable file when linking, when the operating system loads the executable file, the parameter string will not be loaded into In memory. However, the string can be found and printed out by programs such as dumpbin. You can use this identifier to embed information such as the version number into the executable file!

(3) lib: This is a very commonly used keyword to link a library file to the target file

Commonly used lib keywords can help us connect to a library file. 

E.g:

#pragma comment(lib, "user32.lib") 

This command is used to add user32.lib library file to this project

linker: Put a link option into the target file, you can use this command instead of the command line or in the development environment

       To set the link option, you can specify the /include option to force the inclusion of a certain object, for example:

      #pragma comment(linker, "/include:__mySymbol")

You can set the following link options in the program

/DEFAULTLIB

/EXPORT

/INCLUDE

/MERGE

/SECTION

These options are not explained here one by one, please see msdn for details!

5.#pragma resource"*.dfm"

1>Function:

It means adding the resources in the *.dfm file to the project. *.dfm includes the definition of the appearance of the form.
 

Guess you like

Origin blog.csdn.net/xiaolei251990/article/details/83783194