Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How data is stored in memory in C language

2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article shows you how the data in C language is stored in memory, the content is concise and easy to understand, it can definitely brighten your eyes. I hope you can get something through the detailed introduction of this article.

Data type

Common data types

Common data types

Byte char character data type 1short short integer 2int shaping 4long long integer 4long long longer shaping 8float floating point 4double double precision floating point 8

Note:

There is no string type in C language.

About the size of int and long: the C language only specifies: sizeof (long) > = sizeof (int)

The Boolean type (_ Bool) (introduced by C99) is specifically used to indicate true or false, but it can be represented without a Boolean type in C language.

# includeint main () {_ Bool flag = false; _ Bool flag2 = true; if (flag) {printf ("\ n");} if (flag2) {printf ("hehe\ n");} return 0;} / only basic categorized shaping of hehe type is printed

Char also belongs to shaping (each character is stored to store its corresponding ascll value, ascll is an integer)

Charunsigned charsigned charshortunsigned shortsigned shortintunsigned intsigned intlongunsigned longsigned long

Signed and unsigned numbers

Signed number

Int main () {int a = 10; int a =-10; return 0;} / / an is a signed number that can store positive and negative integers / / int = > signed int//short = = > signed short//long = = > signed long

Unsigned number

Some variables are only positive by meaning, such as age, price. These variables can be defined as unsigned numbers, and unsigned numbers can only store positive numbers.

Int main () {unsigned int a = 10; / / an unsigned variable can only store a positive number a =-10; / / even if a negative number is entered here, it will convert the negative number into a positive number (not simply remove the sign, this is about the binary calculation) return 0;}

Is char equal to signed char?

Answer: depends on the compiler

We will find such a thing:

Int is signed int.

Short is signed short.

Long is signed long.

Whether char equals signed char or unsigned char depends on the compiler. Different compilers may have different results. Under common compilers, it is equal to signed char.

Printing for signed and unsigned numbers

Unsigned numbers should be printed with u

% u and% d print are interpreted differently:

When using% d, it will be considered to be a signed number, and when printing, the first bit in the binary will be considered to be a symbolic bit.

When you use% u, it is considered to be unsigned data, and the entire binary sequence is considered to be significant bits.

# includeint main () {unsigned int a = 10; printf ("% u", a); / / correct form / / what happens if you store a-10 in it a =-10; printf ("% u", a); / / prints 4294967286, which is not a random number return 0;}

Why does unsigned shaping store-10 print out 4284967286 (not a random number)?

% u thinks that an is still storing positive numbers at this time, and interprets the complement of a. Explain the details in detail when introducing the original countercomplement later in this chapter.

Floating point type floating point size float4double8 construction type (custom type) construction type

After the array name is removed, what is left is the array's type structure, struct enumeration type, enum union (union) type, union pointer type, pointer type, char* pcint * pifloat* pfvoid* pv null type.

Void represents an empty type (no type)

Usually applied to the return type of the function, the parameter of the function, the pointer type

Plastic storage in memory int a = 10 per int b =-10

Then we observe the storage of an and b in memory.

Data is stored in memory in binary, but the compiler shows us in hexadecimal:

The value of an in memory is: 0a 00 00 00

The value of b in memory is: f6 ff ff ff

Why is it such a value? The source code, inverse code, and complement of integers are described below.

Original code, inverse code, complement code

Integer binaries have three representations, while binary complements are stored in memory.

For example, the original code of 1:

00000000 00000000 00000000 00000001

Positive integer

The original code, inverse code and complement of positive integers are the same

Negative integer

Source code: the binary code written directly according to the plus or minus of a number is the original code.

Inverse code: the symbol bit is unchanged, other bits are reversed by bit (not by bit).

Complement: the binary sequence of the inverse code plus 1

Convert from original code to complement code: take the reverse first and then add one.

Convert from complement to original code: you can subtract and reverse again and again, or you can take the reverse first and then add one (the same process as converting the original code to the complement).

Type data: 15 data:-15 original code 00000000 00000000 00000011000000000000000000000000000111111111111111111111111111111111111110000000000000001111111111111111111111111111111111000000000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

Explain why 4294967286 occurs when% u prints-10;

Using the above method, we can calculate the complement of-10:

Data complement 1011111111 11111111 11111111 11110110

Back to the beginning of using% u print-10 will print as 4294967286, because when using% u, will not interpret the symbol bit, will take the entire 32-bit binary as significant bits, read out a data, and this data is 4294967286.

At the same time, go back to the value of aformab.

Int main () {int a = 10 political int b =-10; / a: 00000000 00000000 00000000 00001010 / / b: 1111111111111111111111111111111111111111110110} / / four binary bits are converted to a hexadecimal bit / / a: 000000 0a//b: ff ff ff f6

Why is it different from what you see in the memory interface?

The memory interface is the opposite of the order we calculated:

Data calculation result memory 1000 00 00 0a0a 00 00 00-10ff ff ff f6f6 ff ff ff

Why would you deposit it backwards?

This is related to byte order. Let's take a look at byte order.

Size end byte order

When the content stored is more than one byte, it will be stored in order.

(data of type char has no byte order. The data of type char is only one byte and has no order)

Machines have two order in which bytes are stored:

Large-end byte order storage:

Low-byte data is stored at high address, and high-byte data is stored at low address.

Small-end byte order storage

Low-byte data is stored at low address, while high-byte data is stored at high address.

Let's use the following example to explain:

Int main () {int a = 0x11223344 X X begins with hexadecimal number / / re-memory interface see: 44 33 22 11 return 0;}

When I was looking at the memory, I found that my machine was stored in mode 2, so my machine used small-end byte order.

So is there any way to quickly determine which byte order the machine you are currently using belongs to?

Design a Mini Program to determine which byte order the current machine belongs to.

# includeint main () {int a = 1; / / hexadecimal of / / an is 00 00 00 01 / / if it is large, then memory is: 00 00 01 / / if it is small, then memory is: 01 00 00 / / you only need to determine whether the content of the first byte is 1 char*pc = (char*) & a / / forced type conversion intercepts the first byte of an if (* pc) / / it can also be: if (* (char*) & a) {printf ("small end");} else {printf ("big end");} return 0;} data truncation and integer promotion during storage

Example 1

Int main () {char a =-1; signed char b =-1; unsigned char c =-1; printf ("% d% d% d", aMae BJM c); / / will print out-1-1 255 return 0;}

Explanation:

Step one:

Here we save three identical integers-1 into two types of variables (char and signed char are equivalent under the VS2019 compiler I use), both of which are of char type

Step 2:

Variables of type char can only store one byte (8 bits) of data, but-1 is a shaping (32 bits)

Here we need to truncate the data: the binary complement of-1 is 11111111 11111111 11111111.

Truncation: assign the last eight bits of the complement to variables a, b, c.

Step 3:

Here, the data of type char needs to be printed as% d, but% d can only interpret integer data (integers have four bytes), while all three variables of type char have only one byte, so integer promotion will occur here:

Plastic lifting: for signed data, high complement bit, for unsigned data: high position complement 0

Data (variable) before shaping lifting (complement) data represented by the original code a/b1111111111111111 111111111111111111111111-1c1111111100000000 0000000000000000011111111255

When d prints, it will think that this is the complement of the data to print, and print the three variables in the form of normal integers.

Example 2

# includeint main () {char a =-128; printf ("% u", a); / / will print 4294967168 return 0;}

Explanation:

Step one:

Observation data:-128 is an integer with 32 bits in binary: but the variable that accepts this data is a variable of type char (only 8 bits can be accepted)

Step 2:

Truncation of data:

Data binary (complement) intercept (a stored part)-12811111111 11111111 11111111 1000000010000000

Lenovo: if a = 128here, then the post-stage value is still 10000000.

Step 3:

Print integers (four bytes), so shaping promotion needs to occur here (an is signed char, high-order complement bit)

Data (variable) before plastic lifting (complement) a1000000011111111 11111111 11111111 10000000

Step 4:

Print this variable in the form of u, because u should print unsigned integers, and the entire 32 bits are considered to be valid bits when printing

It will print out 4294967168.

Floating-point storage in memory common examples of floating-point numbers literal floating-point 3.14159 representation of scientific counting 1E10 (1 times 10 to the 10th power)

Note:

Adding f to the floating point data is the float type. If you don't add it, the default is double type.

% f and% lf default six decimal places

Floating point and plastic surgery are stored in memory differently.

Let's use the following example to explore the difference between floating-point and plastic surgery in memory.

# includeint main () {int n = 9; float* pf = (float*) & n; / / first group printf ("n =% d\ n", n); / / print out: 9 printf ("* pf =% f\ n", * pf); / / print out: 0.000000 / / second group * pf = 9.0; printf ("n =% d\ n", n) / / print out: 1091567616 printf ("* pf =% f\ n", * pf); / / print out: 9.000000 return 0;}

Why did this happen?

Before you answer this question, let's take a look at floating-point binary storage:

International Institute of Electrical and Electronic Engineers (IEEE): any binary floating point number V can be expressed in the following form

Representation: (- 1) ^ S * M * 2 ^ E

(- 1) ^ S represents a symbolic bit, a positive number when S is 0, and a negative number when S is 1

M represents a valid number, greater than or equal to 1, less than or equal to 2

2 ^ E represents the exponential bit

(5.5) Decimal 5.5101.15.5 * (10 ^ 1) 1.011 * (2 ^ 2) Decimal floating point numbers: 5.5 converted to binary: 101.1 can be written as: (- 1) ^ 0 * 1.011 * (2 ^ 2) S = 0m = 1.011E = 2 only need to store three values of SME

The IEEE floating point standard defines two basic formats: a single-precision format expressed in four bytes and a double-precision format represented by eight bytes.

Single-precision floating-point storage format (32 bits)

The first bit, followed by 8 bits, leaves 23 symbolic bits, exponential bits, significant bits.

Double-precision floating-point storage format (64 bits)

The first place is followed by 11 bits, leaving 52 symbolic bits, exponential bits, significant bits.

The IEEE754 has some special rules for the significant number M and index E:

About M:

1. We already know that 1 < = M < 2, that is to say, M must be written in this form: 1.xxxxxx

Where xxxxxx represents the part after the decimal point

two。 When M is stored inside the computer, because the first bit is always 1, the 1 is omitted and only the following fractional part is saved, so that a significant number can be saved. in this way, the accuracy of the stored data can be improved by one bit: for example, in a single-precision floating-point storage format, the last 23 bits are used as significant bits, but the accuracy of the data stored in the computer is 24 digits.

About E:

The computer will think that this is an unsigned number, but there will be a lot of cases in which E takes a negative number in more than a dozen lines, so IEEE754 stipulates that when storing in memory, the true value of E must be added to a median, which is 127for single precision and 1023 for double precision.

For example, for the decimal number 0.5, its binary is 0.1 less E =-1; then we need to add-1 to get 126, and store 126 in the exponential bit.

Take out these stored data (three kinds of chaos) case 1: e is not all 0 or not all 1

E: the real value is obtained by subtracting the exponential bit value by 127 (1023)

M: the value of the significant bit is preceded by 1.

Case 2: e is all 0

E:

The real E is a very small number, close to 0.

At this time, there is no need to calculate, E is directly equal to 1127 (1-1023), which is its true value.

M:

Instead of being preceded by a 1, M is reduced to a decimal of 0.XXXXXX to represent plus or minus zeros and a very small number close to zero.

Case 3: e is all 1

The real E is a very large number, representing a positive or negative infinite number.

Explain the above example

Why does the first group print the integer 9 with% f and print out 0.000000?

Reason:

At this time, E is all 0, which is a very small data, so print 0.000000

Why does 1091567616 print out when * pf is printed in% d in the second group?

The above is how data is stored in memory in C language. have you learned any knowledge or skills? If you want to learn more skills or enrich your knowledge reserve, you are welcome to follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report