4D C language learning notes, take you to learn C and take you to fly (4)


  • C language learning notes, record what you have learned, for easy review. Due to the large space, considering the perception, I plan to divide it into multiple records.
  • Learning video link: "Take you to learn C and take you to fly"
  • IDE:Dev-C++ 5.11
  • In order to develop good programming habits, temporarily abandon Clion
  • Front Row Reminder: Recommended Favorites

Links to series of articles:
Wanzi C language study notes, take you to learn C and take you to fly! (1)
Ten thousand words C language study notes, take you to learn C and take you to fly! (two)


Single list

typedef

There are two purposes of using typedef:

  • One is to give the variable an alias that is easy to remember and has a clear meaning;
  • One is to simplify some of the more complex type declarations.

1. Basic typedefs

typedef is the encapsulation of the type (that is, give the type an alias you like), which is more flexible than the direct replacement of the macro definition.

  • For example, applying the typedef keyword to int
# include<stdio.h>

typedef int integer;

int main()
{
    
    
	integer a;
	int b;
	
	a = 521;
	b = a;  
	
	printf("a = %d\n", a);
	printf("b = %d\n", b);
	printf("a所占字节:%d\n", sizeof(a));
	
	return 0;
}

The output is:

a = 521
b = 521
a所占字节:4

It can be seen that typedef only changes the name of the type, but does not change the essence of the type.

  • Example: Applying the typedef keyword to a structure
# include <stdio.h>
# include <stdlib.h>

typedef struct Date
{
    
    
	int year;
	int month;
	int day;
} DATE;

int main()
{
    
    
	struct Date *date;
	
	date = (DATE *)malloc(sizeof(DATE));  
	//如果不用typedef关键字,这里的DATE应该写成struct Date,使用后方便了一些。 
	if (date == NULL)
	{
    
    
		printf("内存分配失败!\n");
		exit(1);
	}
	
	date->year = 2021;
	date->month = 7;
	date->day = 28;
	
	printf("%d-%d-%d\n", date->year, date->month, date->day);
	
	return 0;
}

output:

2021-7-28

2. Advanced typedefs

Simplify more complex type declarations

  • Example 1:
int (*ptr)[3];
可以改成:
typedef int (*PTR_TO_ARRAY)[3];
  • Example 2:
int (*fun)(void);
可以改成:
typedef int (*PTR_TO_FUN)(void);
  • Example three:
int *(*array[3])(int);
其中:
(*array[3])就是一个指针数组
可以认为是:
int *A(int);
可以改成:
typedef int *(*PTR_TO_FUN)(int);
PTR_TO_FUN array[3];

application:

# include <stdio.h>

typedef int *(*PTR_TO_FUN)(int);

int *funA(int num)
{
    
    
	printf("%d\t", num);
	return &num;
}

int *funB(int num)
{
    
    
	printf("%d\t", num);
	return &num;
}

int *funC(int num)
{
    
    
	printf("%d\t", num);
	return &num;
}

int main()
{
    
    
	PTR_TO_FUN array[3] = {
    
    &funA, &funB, &funC};
	int i;
	
	for (i = 0;i < 3;i++)
	{
    
    
		printf("num的地址:%p\n", (array[i])(i));
		
	}
	
	return 0;
}

output:

0       num的地址:000000000062FDE0
1       num的地址:000000000062FDE0
2       num的地址:000000000062FDE0

Warring will be reported when compiling here

[Warning] function returns address of local variable [-Wreturn-local-addr]

Because we return the value of the local variable here.

Community

Definition format:

union 共用体名
{
    
    
    成员列表
};

The difference between a structure and a union is that each member of a structure occupies different memory and has no influence on each other; while all members of a union occupy the same memory, modifying one member will affect all other members.

The memory occupied by the structure is greater than or equal to the sum of the memory occupied by all members (there may be gaps between members), and the memory occupied by the union is equal to the memory occupied by the longest member. The union uses the memory overlay technology, which can only save the value of one member at a time. If a new member is assigned a value, the value of the original member will be overwritten.

Unions are rarely used in general programming, but are more used in single-chip microcomputers.

enumerated type

If a variable has only a few possible values, it can be defined as an enumerated type.

1. Declare the enumerated type

enum  枚举类型名称  {
    
    枚举值名称, 枚举值名称...};

2. Define enumeration variables

enum  枚举类型名称 枚举变量1, 枚举变量2;
  • Example 1:
# include <stdio.h>
# include <time.h>

int main()
{
    
    
	enum Week {
    
    sun, mon, tue, wed, thu, fri, sat};
	enum Week today;
	struct tm *p;
	time_t t;
	
	time(&t);
	p = localtime(&t);
	
	today = (enum Week) p->tm_wday;  //这里p->tmday返回的是一个整型,要强制转换成枚举类型才能赋值 
	
	switch(today)
	{
    
    
		case mon:
		case tue:
		case wed:
		case thu:
		case fri:
			printf("上课!\n");
			break;
		case sat:
		case sun:
			printf("周末!\n");
			break;
		default:
			printf("Error!!!\n"); 
	 } 
	 
	 return 0;
}

Output: (The test code time is July 29, 2021, Thursday

上课!
  • Example 2:
# include <stdio.h>

int main()
{
    
    
	enum Color {
    
    red, green, blue = 10, yellow};
	enum Color rgb;
	
	printf("red = %d\n", red);
	printf("green = %d\n", green);
	printf("blue = %d\n", blue);
	printf("yellow = %d\n", yellow);
	
	return 0;
}

output:

red = 0
green = 1
blue = 10
yellow = 11

It can be seen that the default is defined from 0, but we can change the default value.

bit field

  • The way to use a bit field is to use a colon (:) and a number after the structure member to indicate the number of digits occupied by the member when the structure is defined.
  • Bit field members can have no name, as long as the data type and bit width are given
  • example:
# include <stdio.h>

int main()
{
    
    
	struct Test
	{
    
    
		unsigned int a:1;
		unsigned int b:1;
		unsigned int c:2;  //这里的数值要比你所存放的内容大
	};
	
	struct Test test;
	test.a = 0;
	test.b = 1;
	test.c = 2;
	
	printf("a = %d, b = %d, c = %d\n", test.a, test.b, test.c);
	printf("size of test = %d\n", sizeof(test));
	
	return 0;
}

output:

a = 0, b = 1, c = 2
size of test = 4

bit manipulation

operator meaning priority example illustrate
~ bitwise inversion high ~a If a is 1, ~a is 0
& bitwise AND middle a&b Only when a and b are 1 at the same time, the result is 1; only if one of a and b is 0, the result is 0
^ bitwise XOR Low a^b If a and b are different, the result is 1; if a and b are the same, the result is 0
l bitwise or lowest a l b Only one of a and b is 1, the result is 1; only a and b are 0 at the same time, the result is 0;
  • Combined with the assignment number

These four operators, except that there is only one operand for bitwise inversion, the other three can be combined with copy (=), which makes the code more concise.

  • shift operator

Shift all bits in a variable left or right.

  • Left shift operator (<<)

For example: 11001010 << 2insert image description here

  • Right shift operator (>>)

Example: 11001010 >> 2
insert image description here

left shift, right shift operatorIf the right operand is negative,orThe right operand is larger than the maximum width supported by the left operand, then the result of the expression belongs to "undefined behavior

Whether the operand on the left is signed or unsigned actually has a different impact on the shift operator. Unsigned numbers are definitely fine, because at this time all the bits in the variable are used to represent the size of the value. But if it is a signed number, it needs to be treated differently, becauseThe first bit to the left of a signed number is the sign bit, so if the operand happens to be a negative number, then the decision to overwrite the sign bit after the shift still falls to the compiler.

  • Can be combined with assignment number

For example:

a <<= 1;  //a = a << 1;

a >>= 1;  //a = a >> 1;

Writing and writing out files

  • read and write single characters

Read: fgetc and getc
Write: fputc and putc

  • read and write the entire string

read: fgets
write: fputs

  • Binary reading and writing files

Read: fread
Write: fwrite

Guess you like

Origin blog.csdn.net/qq_44921056/article/details/119141480