The contents of the second edition of Tan Haoqiang's teaching materials that are being improved: shift, macro definition...bit segment (bit field), conditional compilation...

Preface

The C language is extensive and profound. After reading Tan Haoqiang's "C Language Programming", I found that there were still things that I didn't understand when I encountered open source programs, so I used the book of problem solving and computer guidance to supplement the missing knowledge.

 

First release the contents of the supplementary knowledge part of Tan Haoqiang's "C program computer problem solving and computer guidance"

 

1. Bit operation:

Explanation:
(1) Except for "~", the bitwise operators are all binary (element) operators, which means that there is an operation quantity on each side. For example, a&b.
(2) The object participating in bit operation can only be integer or character data, not real data. The various bit operations are introduced separately below.

#include<stdio.h>
int main()
{
	unsigned a = 0xffffe0ff, b = 0xffffc2ff;
	//%x按16进制输出。
	printf("%x\n", a & b);    //按位与
	printf("%x\n", a | b);    //按位或
	printf("%x\n", a ^ b);    //按位异或
	printf("%x\n", ~a);       //按位取反
	printf("%x\n", a << 4);    //左移4位(乘以2的4次方)
	printf("%x\n", a >> 8);    //右移8位(除以2的8次方)
	printf("这里一个f占4位,即‘1111’,十进制的15\n");
	return 0;
}

 

Example: realize the cycle shift right

#include<stdio.h>
#define WORDSIZE 32 //我现在是X86模式编译,占32位,4字节(32位=4字节)
int main()
{
	unsigned a, b, c;
	int n;
	printf("请输入a和n  \n");
	scanf("%x,%d", &a, &n);
	b = a << (WORDSIZE - n);//书中源码这里是16(字节),我运行发现总是不对,发现我现在是X86模式编译,占32位
	c = a >> n;
	c = c ^ b;
	printf("a:%x \nc:%x", a, c);
	return 0;
}

operation result:

 

The following is from:

https://zhidao.baidu.com/question/165145005.html

Shift - not "shift" operation
n<<3, binary, left shift 3 bits, that is, n=n*2*2*2, that is, n*8
0,1,2,3 - change to 0, 8, 16, 24
x >> 24 The highest byte is moved to the left, and & 0xff is taken out.
x >> 16 The second high byte is moved to the left, and & 0xff is taken out.
x >> 8 The third high byte is moved to the left, and & 0xff is taken out.
x >> 0 does not move, & 0xff is taken out.
For example:
00111111 01010101 11111111 00000001
x >> 8 gets

00000000 00111111 01010101 11111111
x >> 16 gives

00000000 00000000 00111111 01010101
x >> 24 gives

00000000 00000000 00000000 00111111

 

About "bit segment"

C language allows to specify the length of memory occupied by its members in a structure in units of bits ,

This kind of members in units of bits becomes a "bit field" or "bit field" .

Use bit segments to store data with fewer bits

Use "bit segment"

Type name [member name]: width;

#include<stdio.h>

struct Packed_data
{
	unsigned a : 2;
	unsigned b : 2;
	unsigned c : 2;
	unsigned d : 2;
	short i;
}data1;

struct Packed_data2
{
	unsigned a : 2;
	unsigned b : 3;
	unsigned c : 4;
	short i;
}data2;

int main()
{
	printf("%d\n", sizeof(data1));
	printf("%d\n", sizeof(data2));
	return 0;
}

In fact, you will encounter the system's "auto-completion" (occupies at least one storage unit, that is, a machine word (a 64-bit word (WORD) is 8 bytes) ), the result is as shown in the figure above, data2 is also 8 bytes.

*The direction of bit space allocation varies from machine to machine. It is generally assigned from right to left (as shown in the figure).

 

 

2. Pretreatment:

     C language allows adding some "preprocessing directives" to the source program to improve the programming environment and increase programming efficiency. These preprocessing instructions are recommended by the C standard, but they are not part of the C language itself, and they cannot be directly compiled with the C compilation system (because the compiler cannot recognize them). The program must be formal compilation (including morphology and syntax analysis, code generation, optimization, etc.) before the first program in these special instructions "pre-treatment" (preprocess, also known as "pre-compiled" or "pre-compiled" ). The preprocessing instructions are converted into corresponding program segments. They and other parts of the program form a real C language program. The preprocessing of the preprocessing instructions is processed by a program called the C preprocessor (preprocessor) of.

      In the preprocessing stage, the preprocessor deletes all the comments in the program; processes the preprocessing instructions, such as copying the content of the header file specified by the #include directive (such as stdio.b) to the #include directive : to #define Instruction, perform the specified character replacement (such as replacing the symbol constant in the program with the specified string), and delete the preprocessing instruction.

      The pre-processed program no longer includes the pre-processing instruction , and finally the compiler will actually compile the pre-processed source program to obtain the executable target code. Many C compilation systems currently in use regard the C preprocessor as an integral part of the C compilation system, which is done in one go when compiling. Therefore, some users mistakenly think that preprocessing instructions are part of the C language, and even think that they are C statements, which is wrong. The preprocessing directive and the C statement must be correctly distinguished between preprocessing and compilation in order to use the preprocessing directives correctly. An important difference between the C language and other high-level languages ​​is that it can use preprocessing instructions and have preprocessing functions.

1. Preprocessing instructions:

https://www.cnblogs.com/zi-xing/p/4550246.html

  1. #Empty instruction, no effect
  2. #include contains a source code file
  3. #definedefine macro
  4. #undef Cancel the defined macro (restrict scope)
  5. #if If the given condition is true, compile the following code
  6. #ifdef If the macro has been defined, compile the following code
  7. #ifndef If the macro is not defined, compile the following code
  8. #elif If the preceding #if condition is not true, and the current condition is true, compile the following code
  9. #endif end a #if……#else conditional compilation block
  10. #errorStop compilation and display error messages

The book says three situations:

  • Macro definition (3, 4)

"Macro definition" is to replace character strings with specified identifiers (no memory is allocated, so do not use macro names as variable names ); it is also a "condition" of conditional compilation

For example, replace the "3.14" macro with "PI"

#define PI 3.14

Detailed introduction: https://www.jianshu.com/p/2915629103e4

 

  • File contains processing (2)

The "file contains" instruction is very useful, it can save the programmer's repetitive work.

For example, personnel in a certain unit often use a set of fixed symbolic constants (such as g-9.11, pi-3. 1415926, e = 2.71........ These macro definition instructions can be combined into a header file, Then everyone can use the #include directive to include these symbolic constants into the source file they wrote, instead of having to re-define these symbolic constants by themselves, which is equivalent to industrial standard parts and just use them.

#include "BiaoHaoKu"

 

  • Conditional compilation (5, 6, 7, 8, 9)

Conditional compilation is very good for improving the versatility of C source programs.

If a C source program runs on different computer systems, and different computers have a certain difference (for example, some machines store an integer with 16 bits (2 bytes), and some store with 32 bits An integer), so when compiling the program on different computers, it is necessary to make necessary modifications to the source program, which reduces the versatility of the program.

Example: solve int bit length

#ifedf COMPUTER A
    #define INTEGER 16
#cise
    #define INTEGER_SIZE 32
#endif

 If the following command line appeared before the above group of conditional compilation instructions :

#defne COMPUTER_A 0

Or define COMPUTERA as any string, even

# deline COMPUTER_A

That is, as long as COMPUTER_A has been defined , it will work when the program is pre-compiled. After pre-compilation, the INTEGER SIZE in the program is replaced by 16 otherwise it is replaced by 32.

In this way, the source program can be used in different types of computer systems without any modification. Of course, what is introduced above is only a simple situation, readers can design other conditional compilation based on this idea.

Example: Useful in some modes (output information when you want to output information)

#ifedf DEBUG
    printf("开启debug模式。x=%d",x);
#endif

 

2. About #pragma once:

    method one:

    The method of #ifndef relies on the fact that macro names cannot conflict. This not only ensures that the same file will not be included multiple times, but also that two 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.

    #ifndef __SOMEFILE_H__
    #define __SOMEFILE_H__
    ... ... // 一些声明语句
    #endif

 

    Way two:

    #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 benefit 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, duplicate inclusions are easier to find and correct.

    #pragma once
    ... ... // 一些声明语句

 

 

Guess you like

Origin blog.csdn.net/sinat_27382047/article/details/84350670
Bit
BIT