[C language advanced 1 - data storage (1)]


foreword

This article begins to learn the advanced content of C language. The advanced content is to expand on the content of the basic stage, and some knowledge points have also been learned in the basic stage. In the advanced content, learning will be understood from a deeper perspective. The main contents of this article include:

  • Details of data types
  • Storage of shaping in memory: original code, inverse code, complement code
  • Introduction and judgment of big and small endian byte order
  • Storage analysis of floating point type in memory

1. Introduction to data types

The basic types and storage space sizes have been learned in the basic stage.
Know the size of the memory space opened up by a certain type (the size determines the scope of use).

char //字符数据类型
short //短整型
int //整形
long //长整型
long long //更长的整形
float //单精度浮点数
double //双精度浮点数

1.1 Basic classification of types

  • Plastic family
char
	unsigned char//无符号
	signed char//有符号
short
	unsigned short [int]//无符号
	signed short [int]//有符号
int
	unsigned int//无符号
	signed int//有符号
long
	unsigned long [int]//无符号
	signed long [int]//有符号
  • floating point family
float
double
  • Structural type
> 数组类型
> 结构体类型 struct
> 枚举类型 enum
> 联合类型 union
  • pointer type
int *pi;
char *pc;
float* pf;
void* pv;
  • empty type
void 表示空类型(无类型)
通常应用于函数的返回类型、函数的参数、指针类型

2. Storage of shaping in memory

The creation of a variable is to open up space in memory. The size of the space is determined by the type of the variable

//举例
int a = 20;
int b = -10;

int is an integer and occupies 4 bytes. The following will specifically analyze how the value 20 of the variable a is allocated in the memory space

2.1 Original code, inverse code, complement code

There are three representation methods for integers in the computer, namely original code, inverse code and complement code:

  • Original code : directly translate binary into binary in the form of positive and negative numbers
  • **Complement code: **Keep the sign bit of the original code unchanged, and the other bits can be obtained by inverting the other bits in turn.
  • **Complement code: **Complement code +1 to get the complement code

The three representation methods have two parts: sign bit and value bit:

  • The sign bit is 0 for "positive" and 1 for "negative"
  • The original, inverse, and complement of positive integer numbers are the same
  • The three representations of negative integers are different

Note that the integer stored in the memory is the complement , the object of the operator is the complement, and the original code is printed at the end .

Give an example to illustrate the original code, inverse code, and complement code of the value,

//
int main()
{
    
    
	int a = 10;//正数
	00000000 00000000 00000000 00001010 原码
	00000000 00000000 00000000 00001010 反码
	00000000 00000000 00000000 00001010 补码
	a在内存中的存储形式 00 00 00 0a
	int b = -10;//负数
	10000000 00000000 00000000 00001010 原码
	11111111 11111111 11111111 11110101 反码
	11111111 11111111 11111111 11110110 补码=反码+1
	b在内存中存储的数值 ff ff ff f6
	return 0;
}

The storage form of the value of a
insert image description here
in the memory: The storage form of the value of b in the memory:
insert image description here
In the computer system, the value is always represented and stored in the complement . The reason is that, using the complement code, the sign bit and the value field can be processed uniformly;

Since the CPU only has an adder , addition and subtraction can also be processed uniformly. In addition, the complement code and the original code are converted to each other, and the operation process is the same, and no additional hardware circuit is required.

The following will illustrate that the operation of data in memory is performed using the complement code instead of the original code :

int main()使用补码计算,打印的是原码
{
    
    
	1-1//CPU只有加法器
	1+(-1)
	第一步:
	00000000 00000000 00000000 00000001  1补码
	第二步:
	10000000 00000000 00000000 00000001  -1原码
	11111111 11111111 11111111 11111110  -1反码
	11111111 11111111 11111111 11111111  -1补码
	第三步:补码相加
	00000000 00000000 00000000 00000001  1补码
	11111111 11111111 11111111 11111111  -1补码
	结果是33位,超出范围
   100000000 00000000 00000000 00000000 
	00000000 00000000 00000000 00000000   截断32位为0

	如果使用原码计算,结果是错误的
	00000000000000000000000000000001  1补码
	10000000000000000000000000000001  -1原码
	10000000000000000000000000000010  -2
}

2.2 Introduction to Big and Little Endian

2.2.1 What is big and small endian

  • Big- endian (storage) mode means that the low-order bits of the data are stored in the high address of the memory, and the high-order bits of the data are stored in the low address of the memory.
  • Little-endian (storage) mode means that the low-order bits of the data are stored in the low address of the memory, and the high-order bits of the data are stored in the high address of the memory.

2.2.2 Big-endian and little-endian meanings

  • Because in computer systems, we use bytes as a unit, each address unit corresponds to a byte, and a byte is 8bit
  • But in C language, in addition to 8-bit char, there are 16-bit short type and 32-bit long type (depending on the specific compiler)
  • In addition, for processors with more than 8 bits, such as 16-bit or 32-bit processors, since the register width is greater than one byte, there must be a problem of how to arrange multiple bytes. Therefore, it leads to the big endian storage mode and the little endian storage mode.

Example to illustrate the size end, for example: a 16bit short type x, the address in memory is 0x0010, the value of x is 0x1122, then 0x11 is the
high byte, and 0x22 is the low byte.

  • For big endian mode, put 0x11 in the low address, ie 0x0010, and 0x22 in the high address, ie 0x0011
  • For little endian mode, just the opposite

Our commonly used X86 structure is little-endian mode, while KEIL C51 is big-endian mode. Many ARMs and DSPs are in little-endian mode. Some ARM processors can also be selected by hardware to be big-endian or little-endian.

int main()
{
    
    
	int a = 0x11223344;
	return 0;
}

The low byte 0x44 is in the low address, so it is little endian:

insert image description here
insert image description here

2.2.3 Write a program to judge the endianness

Design a small program to determine the endianness of the current machine

int checksys()
{
    
    
	int a = 1;//00 00 00 01
	char* ch = (char*)&a;//char* 截断字节,指针指向低地址数据 
	return *ch;//解引用,返回低地址数据
	//return *(char*)&a;//上面两行代码也可写成一行代码
}
int main()
{
    
    
	int a = checksys();
	if (a==1)//如果低地址保存的数据是1,即0x01,就是低字节
	{
    
    
		printf("小端\n");
	}
	else
	{
    
    
		printf("大端\n");
	}
	return 0;
}

insert image description here


Summarize

The learning of data storage is not over yet.

Continue to learn the knowledge points related to data storage in the next article.

Guess you like

Origin blog.csdn.net/taibudong1991/article/details/124028866