“This is the 8th day of my participation in the First Challenge 2022. For details: First Challenge 2022”

Meaning of type:

The amount of memory opened up with this type, and thus the size determines the scope.

  • It is this type, once identified, that determines the size of its memory space and also determines its range. For example: When you assign the value of a variable to an int integer, its storage size is 4 bytes and the value ranges from -32768 to 32767.
  • Note that the size of each type of storage depends on the system bits, but 64-bit systems are the norm today.

The types of C language are divided into

Basic types: They are arithmetic types and include two types: integer types and floating point types.

Enumerated types: They are also arithmetic types and are used to define variables that can only be assigned discrete integer values in a program.

Void type: The type specifier void indicates that no value is available.

Derived types: They include pointer types, array types, structure types, common types, and function types. How do you get a clear view of a memory space, which is essentially assuming you

How to look at memory space: The int type creates a variable (a) that takes up four bytes, while the float type creates a variable (b) that takes up only four bytes. But the format %d given to variable A is an integer, and the format %f given to variable B is a single-precision floating-point type.

Notice that they are stored differently, and you can see that they have different memory using debugging content on the compiler

Int a = 5; Float b = 5.0; Use debugging to get it in memory.

  • Memory is a major part of a computer that holds programs and data while a process is running. It is also called executable memory. In computers, memory space generally refers to main memory space (physical address space) or memory space allocated by the system for a user program. Methods to expand the memory space generally include increasing the memory size and virtual memory.

I’m not going to talk about the other types here, just the constructor types, and the pointer types.

Structural type

  1. Array types: Why are array types constructor types? Int arr[20] is an array. So int [20] is a type, so LET me make one more change int [10] is changing all the time so what if you’re a different type character, floating point, so array is also a custom type and a construct.
  2. Struct type: **struct, ** when a member type is changing, its structure is also changing. If you are not familiar with structure, you can check out the content of this structure in my article.
  3. Enumeration type: **enum, ** This is a key word of C language, when the time will come out to write an article to everyone to explain this enumeration type in C language play a what kind of role.
  4. The type of union: union, which is also called a Commons, which we won’t talk about right now.

Pointer types

  • The purpose of a pointer is to hold an address assigned to a variable within it, and the bytes of a pointer are four bytes.
  • Pointer type is a special type of pointer. Pointer type is a special type of pointer. Pointer type is a special type. Note that the pointer is defined with *💨
#include<stdio.h> int main(void) { int a = 10; int* p = &a; Printf ("%d\n", sizeof(int*)); printf("%d\n", sizeof(int*)); printf("%d\n", sizeof(short*)); printf("%d\n", sizeof(double*)); printf("%d\n", sizeof(char*)); }Copy the code

  • Running results:

Empty type

  • A special return type that represents an empty function, that is, a function that has no return value. Void is used to show that a function does not return any value. We can also specify a pointer to void, which can then point to various types of data objects 💫
  • Void takes no arguments, when you define the program with no arguments, although the program will also run. But there will be a waring hint for parameters that are not needed

The return type of the function ☮

#include<stdio.h>
void print()
{
    printf("hello word\n");
}
int main(void)
{
    print();
}
Copy the code

The argument to the function ☪

#include<stdio.h> void print() {printf("hello word\n"); } int main(void) { print(10); // Give the argument 10} in the print functionCopy the code

Shaping the storage space in memory

If you want to understand this, let me show you some code:

#include<stdio.h>
int main(void)
{
    int a = 5;
    int b = -3;
}
Copy the code

A Stored result

B Stored results

  • Did you notice that the storage results of these two are different, and I’m going to tell you how the plastic is stored in memory.

  • It’s all about understanding the concepts of source code, inverse code, and complement.

  • There are three ways to represent signed numbers in computers: source code, inverse code and complement code. There are two parts of the symbol bit and the numeric bit. The symbol bit of ** is 0 to represent the bit “positive”, and 1 to represent the bit “negative”. The three ways of representing the numeric bit are different. Note: unsigned source code inverse and complement are the same 💨.

  • There are two kinds of signed numbers: one is called positive and the other is called negative. In positive numbers they are the same, but in negative numbers they are expressed differently 💨

The original code: 1

The original code: 1

. 1001

0001

Radix-minus-one complement: 1

Radix-minus-one complement: 1.

. 1110

0001

Complement: 1

Complement: 1

. 1111

0111

  • The above is the negative form of three cases,……….. This is an ellipsis and if you’re doing the integer the first 32 digits, notice that the highest digit here is 1, so there are three forms of a negative number.

The original code

  • Directly the number in accordance with the positive or negative form to convert the translation into binary 💨

    int a = 5; / / 4 bytes, 32 bit bit / / 0 (positive) 0000000000000000000000000000101 int b = 3; / / 1 (negative) 1111111111111111111111111111101

There’s actually another way to do the complement and that’s what I started with:

1. If the complement of negative 1 is assumed to be negative 1, you should first consider the original number of negative 1 — 10001.

2, and then direct inverse code attention to the highest not inverse code – 11110

3, the most critical step is the complement code to remember that the last one plus 1 is 1 to the front of the number into 1, the result is — 11111

Of course, this is a stupid way, if you can not understand the word with this is also ok I am so 😂 at the beginning

Radix-minus-one complement

Will your symbol bit unchanged, that is, the highest bit unchanged, and then in turn according to the bit to get the inverse code.

Int = -10; Radix-minus-one complement is – 11111111111111111111111111110101

complement

The complement is the inverse +1 to get the complement, note that the premise is to inverse +1 💨

Int = -10; The complement of is – 11111111111111111111111111110110

Note here is full 2 into 1, do not mistake ~!

If it is positive: the source, complement and inverse are all the same!

Negative is what I said above! For plastic storage are complementary code, remember!

One byte =8 bits

Why is complement stored in the computer?

In computer systems, values are represented by complement codes. The reason is that, using complement code, the sign bit and number range can be unified processing; At the same time, addition and subtraction with complement code can also be unified processing (CPU only adder), in addition, especially complement code and the original code operation process can be converted to each other!

So I’m going to focus on the adder, the adder is actually the addition operation that the CPU uses. Ok, so I’m going to give you an example: 1-1 so what do you do if you convert to an adder? It’s really easy to just say: 1 + (-1), so what if you want to do it in original code?

One of the original code: 00000000000000000000000000000001

– 1 original code: 10000000000000000000000000000001

Results: 10000000000000000000000000000010 so, 1 + (1) = 2? The answer is clearly not

Good! So now what if we use the complement

1000 0000 0000 0000 0000 0000 0001

The complement of -1 is 1111 1111 1111 1111 1111 1111 1111 1111 1111

Results:

1

0000 0000 0000 0000 0000 0000

But that can only be stored in our plastic is 32 bit, so the left is 0, so use operations complement when we can work out a proper married, think of this, I really think at that time to create this algorithm to estimate is a fairy 😯, multiplication is put add how much ^ a few times, can also be converted to a certain operation. But it’s the same principle that I can do all of these things if I have addition.

Introduction to big end and small end:

  1. Big end: In storage mode, the low bits of memory are stored in the high bits of memory, while the high bits of data are stored in the low bits of memory.
  2. Small end: In storage mode, the low bits of data are stored in the low address of memory, while the high bits are stored in the low address of memory.
  • The memory space is numbered, and we call the lower part of the memory a lower address, and if the number is large, it’s called a higher address, and the data can be stored in any way, But when you return it to your program and you have to store it in whatever way you want to store it, say, 11, 22, 44, 33 (binary conversion hexadecimal 1 byte =4 bits), you’ll need to store it in that way, too. 11, 22, 44, 33! But we don’t usually store memory that way. There are usually two storage methods one is called big endian storage and one is called small endian storage.
  • Suppose: 0x11223344, the 44 is the low level, and 11 is the high level, so the low level is stored in the high number of addresses in memory, and the high level of data is stored in the low address — the big end
  • Again, suppose: 0x44332211, this 44 is the low address, and 11 is the high address. The low byte data is stored at the low address in memory, and the high byte data is stored at the high address — the little endian

Judge the big end and the small end

Use code to determine the big end and the small end:

A number a, stored in memory, suppose this a is 20, in the case of unknowingly, do not know whether the current is a small or large end of the storage. However, it is possible to speculate whether it is big end or small end, as stated above. We can look at their first byte, for example:

  • Int a = 1;
  • Small end: 0x01 00 00 00
  • Big end: 0x00 00 00 01

Code demo

#include<stdio.h> int main(void) { int a = 1; char *p = (char*)&a; If (*p == 1) {printf(" little end \n"); } else {printf(" big end \n"); } return 0; }Copy the code

Custom function code

#include<stdio.h> int Testing() { int a = 1; char * pb = (char*)&a; if (*pb == 1) return 1; else return 0; } int main(void) { int ret = Testing(); If (ret == 1) {printf(" little end \n"); } else {printf(" big end \n"); } return 0; }Copy the code

Here’s what pointer types mean

  1. The pointer type determines how many bytes the pointer dereference accesses, for example :char *p; So here *p can access only one byte, depending on your own defined data type 💨
  2. The type of pointer determines the number of bytes in the pointer +1, for example: char * p +1; So we’re skipping one byte int is 4 bytes based on the data type
  • Note: the integer promotion fills the sign bit of the highest bit, ‘0’ is positive and ‘1’ is negative 💨

The memory storage of floating-point types

Common floating point numbers:

  • 3.14 * 1E10 (this is actually 1.0 * 10 to the 10th * E)

Floating point numbers include:

  • Floating point types in C include float, double, and long double.

Examples of notation:

  1. Column 1 is general notation;
  2. Column 2 is scientific notation;
  3. The third column is exponential notation (or e notation);
  • This is scientific notation written on a computer, the number after e is the exponent of 10;

Here’s a code:

#include <stdio.h> int main(void) { int n = 9; float *pFloat = (float *)&n; Printf ("*pFloat value :%d\n",n); Printf ("*pFloat value :%lf\n", *pFloat); * pFloat = 9.0; Printf ("num :%d\n", n); Printf ("*pFloat value :%lf\n",*pFloat); return 0; }Copy the code

  • Running results:

  • As can be seen from the above code: floating point and integer memory storage form is not the same!
  • PFloat = 0.000000; pFloat = 1091567616; pFloat = 0.000000; Okay, take your time and tell me why!
  • Print :0.000000 because: the plastic form put in the form of floating point back, we can not get a result, that can not explain the plastic storage results and floating point storage is not the same, if the same that is the same result ✨

  • Print :1091567616 because: *pFloat we stored it as a floating point number, and then as a positive n when taken out as an integer, took out an error value ✨

  • This explains the difference between the storage of integers and floating-point types 💨

  • Floating point binary complement

  • For example: 7.0-0111-0111.0 (a 0 after the decimal point will do) this is the binary representation of 7.0 😉

  • Any binary floating point number V can be expressed as follows:

  • Minus 1 to the M times 2 to the E

  • (-1) ^ s represents the sign bit. When s= 0, V = positive (any number raised to the 0 power except 0 is equal to 1) and when s=1, V = negative

  • M is a significant number, greater than or equal to 1, less than 2

  • 2 to the E is the exponent bit

Storage schema diagram:

  • Example: Floating point 9.0
  • 1001
  • 1001.0
  • 1.001 * 2 ^ 3 — Note: this is binary
  • (-1) ^ 0 * 1.001 * 2 ^ 3 = (-1) ^ M * 2 ^ E
  • 0 10000010 00100000000000000000000 —— E = 3 + 127 = 130
  • As the original code directly printed is the number we said above 1091567616
  • It can be determined that — s = 0, M = 1.001, E = 3, note that M = 1.001 is actually: 0001
  • Example: Float 0.5
  • 0.5
  • 0.1 – Note: this is the binary number -1 and for the decimal point, the first digit is 2 to the minus 1 which is 0.5
  • 1.0 * 2 ^ -1 – Convert to scientific notation
  • (-1 ^ 0) * 1.0 * 2 ^ -1 – Note that the exponent E is treated as an unsigned number
  • S = 0, M = 1.0, E = -1
  • For an 8-digit E, the middle number is 127. For an 11-digit E, the middle number is 1023, which is essentially if your E is negative, take -1 for example. For an 8-digit E, it’s -1+127, which is 126
  • E is not all 0’s and it’s not all 1’s

  • Floating point 5.5

  • 101.1 // The first is 101, and the second is 2 to the minus 1 = 0.5

  • (-1) ^ 0 * 1.001 * 2 ^ 2

  • S = 0, M = 1.011, E = 2 (E+127=129)

  • 0100 0000 1011 0000 0000 0000 0000 0000 – the store of E is 129, the value of E is still 129-127=2, if you are a double number then you have to subtract 1023 to get the true value of E

  • 0x40B00000 — Converted out of binary to hexadecimal digits

  • The result of debugging memory:

  • E is all 0.

In this case, the floating-point exponent E equals 1-127(or 1-1023), which is the true value, and the significant number M no longer adds the first 1, but restores the decimal place 0. XXXXXX, which is used to represent ±0 and very small numbers close to 0.

  • E is all 1.

In this case, if the significant digits M are all zeros, it means ± infinity (plus or minus depending on the sign bit s).