Data and C - 4D Detailed Explanation (C Primer Plus)

foreword

Programs cannot do without data. When you feed data, letters, and words into a computer, you expect it to use the data to perform certain tasks. For example, you need to calculate an interest or display a sorted list of vintners. In addition to introducing how to read data, this article will also teach readers how to manipulate data.
C language provides two series of multiple data types. This article will detail two major data types: integer types and floating point types, detailing what these data types are, how to declare them, how and when to use them. In addition, the difference between variables and constants will be introduced.

1 Variable and constant data

Under the guidance of the program, the computer can do many things, such as numerical calculations, drawing, calculating comet orbits or other things you want to do. To accomplish this task, programs need to use data, that is, numbers or characters that carry information . Some data types are preset before the program is used and do not change during the entire running process. These are called constants. Other data types may either change or be assigned values ​​during runtime, these are called variables . For example, 3.1415 is a constant, and weight is a variable, which can be changed through assignment and other methods.

2 Data: data type keywords

Not only are variables and constants different, but there are also differences between different data types (some data types represent numbers, and some data types represent characters). C distinguishes and uses these different data types by recognizing some basic data types . If the data type is a constant, the compiler will identify the type by the form written by the user (for example, 43 is an integer, 43.0000 is a floating point number). But for variables, you need to specify their type when declaring, which will be described in detail later. Now let's take a look at the basic type keywords of the C language.

insert image description here
In the C language, the int keyword is used to represent the basic data type. The latter three keywords (long, short, and unsigned) and the new signed in C90 are used to provide variants of the basic integer types. For example unsigned short int and long long int. The char keyword is used to specify letters and other characters (such as #, &, @ and *). In addition, the char type can also represent smaller integers.. float, double, and long double represent numbers with a decimal point. The _Bool type represents a Boolean value (true or false), and _Complex and _Imaginary represent complex and imaginary numbers, respectively.
The types created by these keywords can be divided into two basic data types according to the storage method of the computer: integer type and floating point number type.

2.1 Integers and floating point numbers

Integer type? Floating point type?
For us, the difference between integers and floating point numbers is how they are written. For computers, the difference between them is the storage method.

2.2 Integer

Like mathematical concepts, in C language, integers are numbers without decimals. At the same time, computers store integers numerically in binary . For example, the integer 7 is 111 in binary. Therefore, to store this number in an 8-bit byte, you need to set the first 5 bits to 0 and the last 3 bits to 1 (as shown in Figure 3.2)

insert image description here

2.3 Floating point numbers

Floating-point numbers are similar to real numbers in mathematics. 2.34, 3.43E7, 6.00, and 2e-4 are all floating point numbers. Note that adding a decimal point to a value makes the value a floating point number. Therefore, 6 is an integer and 6.00 is a floating point number.
However, it should be noted that integers and floating point numbers are stored differently in computers. Computers represent floating-point numbers by dividing them into fractional parts and exponent parts, and store the two parts separately . So while 6.00 and 6 are numerically equal, they are stored differently. In decimal, 6.0 can be written as 0.6E1. Here 0.6 is the fractional part and 1 is the exponent part.

insert image description here

Tips:

  • Integers have no fractional part, floating point numbers have a fractional part.
  • Floating point numbers can represent a larger range than integers.
  • For some arithmetic calculations (eg, subtracting two very large numbers), floating-point numbers lose even more precision .
  • Because there are infinitely many real numbers in any interval (eg. between 1.0 and 2.0), the computer's floating-point numbers cannot represent all values ​​in the interval, and floating-point numbers are usually only approximations of actual values . For example, 6.0 might be stored as the floating point value 5.99999.
  • In the past, floating-point operations were slower than integers. But many CPUs now include floating-point processors, closing the gap in speed.

3 C language basic data types

3.1 int type

The C language provides many data types, why is one type not enough? Because the C language allows programmers to choose different types for different situations. In general, the int type can be used, but in order to meet the requirements of specific tasks and machines, other types can also be selected.
The int type is a signed integer, and its value range varies depending on the computer system. Generally speaking, storing an int takes up one machine word length . In general, systems use the value of a special bit to represent the sign of a signed integer.

3.1.1 Declaring an int variable

//int 两种声明方式
int num;
int hogs,cows,goats;

3.1.2 Initialize variables

The above declarations just create variables, but don't give them values. How do variables get values? The C language provides 3 implementations. The first is assignment, and the second is to obtain the value through scanf(). The third is initialization.

To initialize a variable is to assign an initial value to the variable. In C, initialization can be done directly in the declaration. Simply follow the variable name with the assignment operand (=) and the value to assign to the variable.

int hogs=23;
int cows 123 , goats=12;
int dogs , cats=100; //有效,但这种代码风格很糟糕

In short, initialization creates and marks storage space for variables and assigns them initial values.

insert image description here

3.1.3 Print int value

We can use the printf() function to print the value of int, and use %d (conversion specification) to specify the format in which printf() will display a value. This value can be a variable of type int, a constant, or a constant expression of type int.

#include <stdio.h>
int main()
{
    
    
	int a = 10;
	int b = 2;
	printf("%d %d %d", a, 2, a - b);//变量、常量、表达式
	return 0;
}

insert image description here

3.1.4 Octal and Hexadecimal

Normally, the C language assumes that integer constants are decimal. But when it comes to expressing computer-related values, octal and hexadecimal are obviously more convenient (both are powers of 2). In the C language, that base is used when expressed with a specific prefix. The 0x and 0X prefixes represent hexadecimal (decimal 16 is represented as 0x10 or 0X10 in hexadecimal), and 0 represents octal (decimal 16 is represented as octal is 020) .

3.1.5 Display octal and hexadecimal

In the C language, you can use and display numbers in different bases. Different bases require different conversion specifications. To display a number in decimal, use %d; to display a number in octal, use %o; to display a number in hexadecimal, use %x. In addition, to display the prefixes 0, 0x, and 0X of each base number, you must use %#o, %#x, and %#X respectively .

#include <stdio.h>
int main()
{
    
    
	int x = 100;
	printf("dec=%d; octal=%o; hex=%x\n", x, x, x);
	printf("dec=%d; octal=%#o; hex=%#x\n", x, x, x);
	return 0;
}

insert image description here

3.2 Other data types

In the C language, besides int, there are other integer types that need to be understood.
C language provides three subsidiary keywords to modify the basic integer types: short, long and unsigned.

  • The short int type (abbreviated as short) may occupy less storage space than the int type, and is often used in occasions with small values ​​to save space. (signed type)
  • Long int or long may occupy more storage space than int, which is suitable for
    occasions with large values. (signed type)
  • long long int or long long (added by the C99 standard) may occupy more storage space
    than long, and is suitable for occasions with larger values. The type occupies at least 64 bits. (signed type)
  • unsigned int or unsigned is only used for non-negative values. This type
    does not represent the same range as a signed type. For example, the allowed value range of 16-bit unsigned int is 0
    ~65535, not -32768~32767. The bit used to represent the sign is now used to represent
    another binary bit, so unsigned integers can represent larger numbers. In the C90 standard, the types unsigned long int or unsigned long and unsigned int or unsigned short were added. The C99 standard added unsigned long long int or unsigned long long.

Tips:
The C language only stipulates that the storage space occupied by short cannot be more than int, and the storage space occupied by long cannot be less than int, so as to adapt to different machines.

3.3 Integer overflow

What happens if integer overflows?

//2147483647和2147483647分别为int和unsigned int所能表达最大值
#include <stdio.h>
int main()
{
    
    
	int i = 2147483647;
	unsigned int j = 2147483647;
	printf("%d %d %d\n", i, i + 1, i + 2);
	printf("%u %u %u\n", j, j + 1, j + 2);
	return 0;
}

insert image description here
The reader can think of the unsigned integer j as the odometer of a car. When it reaches the maximum value it can represent, it will restart from the starting point. The same is true for the integer i. Their main difference is that when the maximum value is exceeded, the variable j of unsigned int type starts from 0; while the variable i of type int starts from −2147483648 . Note that the system does not notify the user when i exceeds (overflows) the maximum value that its corresponding type can represent. Therefore, you must take care of such problems yourself when programming. Overflow behavior is undefined behavior, and the C standard does not define overflow rules for signed types. The overflow behavior described above is typical, but other situations may also occur.

3.4 Print short, long, long long and unsigned types

To print the value of unsigned int type, use %u conversion description; to print the value of long type, use %ld conversion description. %lx means to print long type integers in hexadecimal format, and %lo means to print long type integers in octal format . Note that although C allows uppercase or lowercase constant suffixes, only lowercase can be used in conversion declarations .
For the short type, the h prefix can be used. %hd means to display the integer of type short in decimal, and %ho means to display the integer of type short in octal. Both h and l prefixes can be used with u to denote unsigned types. For example, %lu means to print the value of type unsigned long. For systems that support the long long type, %lld and %llu represent signed and unsigned types, respectively.

#include <stdio.h>
int main()
{
    
    
	short end = 200;
	long big = 65537;
	long long verybig = 12345678908642;

	printf("end=%u and not %d\n", end, end);
	printf("big=%ld and not %hd\n", big,big );
	printf("verybig=%lld and not %ld\n", verybig,verybig );
	return 0;
}

insert image description here

  • For the variable end of the short type, the printed value is the same no matter whether the short type (%hd) or the int type (%d) is specified to print in printf(). This is because the C compiler automatically converts short values ​​to int values ​​when passing parameters to functions.

Why do you want to convert? What is the h modifier for?
The conversion is done because the int type is considered the most efficient type for computers to handle integer types. Therefore, in computers where the sizes of the short and int types are different, it is faster to pass parameters with the int type.
Use the h modifier to show that larger integers are truncated to short values.

4 Characters used: char type

The char type is used to store characters (such as letters or punctuation marks), but technically, char is an integer type. Because the char type actually stores integers rather than characters. Computers use numeric encoding (ASCII encoding) to process characters.

insert image description here

4.1 Declaring char type variables

//char类型变量的声明方式与其他类型变量的声明方式相同
char ibs;
char its,ics;
//以上声明创建了3个char类型的变量:ibs、its、ics

4.2 Character constants and initialization

If you want to initialize a character constant to the letter A, you don’t need to memorize the ASCII code, just assign the letter A to the variable through the following initialization:

//以变量名为grade为例
char grade = 'A';

In the C language, a single character enclosed in single quotes is called a character constant. As soon as the compiler finds 'A', it converts it to the corresponding code value.

char ibs;	//声明一个char类型变量
char ibs='T';	//正确赋值
char ibs=T;		//错误!T为变量
char ibs="T";	//错误!"T"是一个字符串

4.3 Non-printing characters

Single quotation marks are only applicable to characters, numbers and punctuation marks. If you browse the ASCII table, you will find that some ASCII characters cannot be printed. For example, characters that represent actions (eg, backspace, newline, terminal beep or beep). C language provides 3 ways to represent these characters. The first method was introduced earlier - using ASCII code. For example, the ASCII value of the beep character is 7, so it can be written like this: char beep = 7; The second method is to use special symbol sequences to represent some special characters. These sequences of symbols are called escape sequences

insert image description here

4.4 Print characters

The printf() function uses %c to indicate the character to be printed. A character variable is actually stored as a 1-byte integer value, so if you print the value of a type variable with the %d conversion, it prints an integer. The %c conversion specification tells printf() to print the character corresponding to the integer value.

#include <stdio.h>
int main()
{
    
    	//以字符C为例
	char ch;
	scanf("%c", &ch);
	printf("%d %c", ch, ch);
	return 0;
}

insert image description here
insert image description here

5 _Bool type

The C99 standard adds the _Bool type to represent Boolean values, namely the logical values ​​true and false. Because the C language uses a value of 1 to represent true and a value of 0 to represent false, the _Bool type is actually an integer type. But in principle it only takes up 1 bit of storage space, because for 0 and 1, 1 bit of storage space is enough.

6 float、double和long double

Various integer types are sufficient for most software development projects. However, programs oriented towards finance and mathematics often use floating point numbers. The floating-point types in C language include float, double, and long double types. Floating-point types can represent a larger range of numbers including decimals. Floating-point numbers are represented similar to scientific notation (i.e. decimals multiplied by powers of 10 to represent numbers). This number system is often used to represent very large or very small numbers. Table 3.3 lists some examples. The first column is general notation; the second column is scientific notation; the third column is exponential notation (or e notation), which is the way scientific notation is written in computers, followed by e The numbers represent the exponent of 10.

insert image description here

The C standard stipulates that the float type must be able to represent at least 6 significant figures, and the value range is at least 10-37~10+37. The previous provision means that the float type must be able to represent the first 6 digits of 33.333333 as numbers, rather than being accurate to 6 decimal places . The latter provision is used to conveniently represent such as the mass of the sun (2.0e30 kilograms), the charge of a proton (1.6e-19 coulombs. Usually, the system takes up 32 bits to store a floating point number. Among them, 8 bits are used to represent the exponent Value and sign, the remaining 24 bits are used to represent the non-exponent part (also called the mantissa or significand) and its sign.
Another floating-point type provided by the C language is double (meaning double precision). The double type and float The minimum value range of the type is the same, but it must be able to represent at least 10 significant figures. In general, double occupies 64 bits instead of 32. Some systems use all the extra 32 bits to represent the non-exponent part, which not only increases The number of significant digits is increased (that is, the precision is increased), and rounding errors are also reduced. Other systems allocate some of these bits to the exponent part to accommodate larger exponents, thereby increasing the range of representable numbers. Regardless of the method, the value of the double type has at least 13 significant digits, which exceeds the standard minimum number of digits. The
third floating-point type of the C language is long double, which meets higher precision requirements than the double type. However , C only guarantees that the long double type has at least the same precision as the double type.

6.1 Declaring floating-point variables

float ibc,ibs;
double ibd;
float ibf=6.63e-34;
long double ibg;

6.2 Floating-point constants

In code, floating-point constants can be written in various forms. There can be no decimal point (eg, 2E5) or exponent part (eg, 19.28), but not both. Either the fractional part (eg, 3.E16) or the integer part (eg, .45E-6) can be omitted, but not both.

3.14159
.2
4e16
.8e-2
123.

Tips:
By default, the compiler assumes that floating-point constants have the precision of type double.

//假设some是浮点型变量
some=3.0*4.0;

Typically, 3.0 and 4.0 are stored as 64-bit doubles, multiplied using double precision, and then truncated to the width of a float. Although the calculation accuracy is higher in this way, it will slow down the running speed of the program.

The C99 standard adds a new floating-point constant format—hexadecimal representation of floating-point constants, that is, adding a hexadecimal prefix (0x or 0X) before the hexadecimal number, using p and P is substituted for e and E respectively, and powers of 2 are substituted for powers of 10 (ie, p-notation). As follows:

0xa.1fp10

Hexadecimal a is equal to decimal 10, .1f is 1/16 plus 15/256, p10 is 2^10 or 1024. The value represented by 0xa.1fp10 is (10+1/16+15/256)×1024 ( That is 10364.0 in decimal).

6.3 Printing floating point values

The printf() function uses %f and %lf conversion instructions to print floating-point numbers of type float and double in decimal notation, and uses %e to print floating-point numbers in exponential notation. If the system supports floating-point numbers in hexadecimal format, a and A can be used instead of e and E, respectively. To print the long double type, use %Lf, %Le or %La to convert it. When passing parameters to functions that do not explicitly specify the parameter type in the function prototype (for example, printf()), the C compiler will automatically convert the value of type float to type double.

#include <stdio.h>
int main()
{
    
    
	float ibs = 32000.0;
	double ibc = 2.14e9;
	long double ibf = 5.32e-5;
	printf("%f can be written %e\n", ibs, ibs);
	printf("And it's %a in hexadecimal,powers of 2 notation\n", ibs);
	printf("%f can be weitten %e\n", ibc, ibc);
	printf("%Lf can be written %Le\n", ibf, ibf);
	return 0;
}

insert image description here

6.4 Overflow and underflow of floating-point values

First, let's take a look at this code

#include <stdio.h>
int main()
{
    
    
	float toobig = 3.12E123*10000000;
	printf("%f", toobig);
	return 0;
}

insert image description here
Here is an example of overflow. Overflow occurs when a calculation results in a number that is too large to be expressed by the current type. This behavior was undefined in the past, but now the C language specifies that toobig is assigned a specific value representing infinity in this case, and printf() displays that value as inf or infinity (or some other value that means infinity) content) .
Let's take a look at this code next

#include <stdio.h>
int main()
{
    
    
	float x = 0.1234E-2;
	printf("%f", x/10);
	return 0;
}

insert image description here

The situation is more complicated when dividing by a very small number. Numbers of type float are stored in exponent and mantissa parts. There exists a number whose exponent is the minimum value, the smallest mantissa value represented by all available bits. The number is the smallest number that the float type can represent with full precision. Now divide it by 2. Usually, this operation reduces the exponent part, but in the hypothetical case, the exponent is already at a minimum. So the computer has to shift the bits of the mantissa to the right, freeing up the first binary bit, and discarding the last binary number. Taking decimal as an example, dividing a number with 4 significant digits (for example, 0.1234E-10) by 10 yields 0.0123E-10. Although the result is obtained, the number on the original effective digit at the end is lost in the calculation process. This situation is called underflow. The C language refers to a floating-point value that loses the full precision of its type as a subnormal floating-point value. So dividing the smallest positive floating point number by 2 will give you a subnormal value. Dividing by a very large value will result in all bits being 0.

7 Complex and imaginary types

Complex and imaginary numbers are used in many scientific and engineering calculations. The C99 standard supports complex and imaginary types, but with reservations. In general, imaginary types are optional. The C11 standard makes the entire complex package optional.
In short, C language has 3 types of complex numbers: float_Complex, double_Complex and long double_Complex. For example, a variable of type float _Complex shall contain two values ​​of type float, representing the real and imaginary parts of a complex number, respectively. Similarly, the three types of imaginary numbers in C language are float _Imaginary, double_Imaginary and long double _Imaginary.

end

This is the end of this article. If it is helpful to you, remember to like and pay attention! thank you for your support!

Guess you like

Origin blog.csdn.net/Zhenyu_Coder/article/details/130440235