4D C 言語学習ノート、あなたを C の学習に連れて行き、あなたを飛ばしてください (4)


  • C 言語の学習ノート。学習内容を記録し、簡単に復習できます。スペースが広いため、認識を考慮して、複数のレコードに分割する予定です。
  • 学習ビデオ リンク: 「Take you to learn C and take you to fly」
  • IDE:Dev-C++ 5.11
  • プログラミングの良い習慣を身につけるために、Clion を一時的に放棄する
  • 最前列リマインダー: おすすめのお気に入り

一連の記事へのリンク:
Wanzi C 言語学習ノート、C の学習に連れて行って、あなたを飛ばしてください! (1)
万語の C 言語学習ノート、あなたを C の学習に連れて行って、あなたを飛ばしてください! (二)


単一リスト

typedef

typedef を使用する目的は 2 つあります。

  • 1 つは、覚えやすく、明確な意味を持つエイリアスを変数に与えることです。
  • 1 つは、より複雑な型宣言のいくつかを単純化することです。

1.基本的なtypedef

typedef は型のカプセル化 (つまり、型に好きなエイリアスを与える) であり、マクロ定義を直接置き換えるよりも柔軟です。

  • たとえば、typedef キーワードを 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;
}

出力は次のとおりです。

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

typedef は型の名前を変更するだけで、型の本質を変更しないことがわかります。

  • 例: typedef キーワードを構造体に適用する
# 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;
}

出力:

2021-7-28

2. 高度な typedef

より複雑な型宣言を簡素化する

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

応用:

# 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;
}

出力:

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

ここでコンパイルすると戦争が報告されます

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

ここでローカル変数の値を返すためです。

コミュニティ

定義形式:

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

構造体と共用体の違いは、構造体の各メンバーが異なるメモリを占有し、互いに影響を与えないことです。共用体のすべてのメンバーは同じメモリを占有しますが、1 つのメンバーを変更すると、他のすべてのメンバーに影響します。

構造体が占有するメモリは、すべてのメンバーが占有するメモリの合計以上であり (メンバー間にギャップがある場合があります)、共用体が占有するメモリは、最長のメンバーが占有するメモリと同じです。ユニオンは、一度に 1 つのメンバーの値しか保存できないメモリ オーバーレイ テクノロジを使用します。新しいメンバーに値が割り当てられると、元のメンバーの値は上書きされます。

共用体は、一般的なプログラミングではめったに使用されませんが、シングルチップ マイクロコンピュータでより多く使用されます。

列挙型

変数に可能な値が少ない場合は、列挙型として定義できます。

1.列挙型を宣言する

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

2. 列挙変数を定義する

enum  枚举类型名称 枚举变量1, 枚举变量2;
  • 例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;
}

出力: (テスト コードの時間は 2021 年 7 月 29 日木曜日です。

上课!
  • 例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;
}

出力:

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

デフォルトは 0 から定義されていることがわかりますが、デフォルト値を変更できます。

ビットフィールド

  • ビット フィールドを使用する方法は、構造体が定義されているときにメンバーが占有する桁数を示すために、構造体メンバーの後にコロン (:) と数字を使用することです。
  • データ型とビット幅が指定されている限り、ビット フィールド メンバーに名前を付けることはできません。
  • 例:
# 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;
}

出力:

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

ビット操作

オペレーター 意味 優先順位 例証する
ビットごとの反転 高い ~a a が 1 の場合、~a は 0 です
& ビットごとの AND 真ん中 a&b aとbが同時に1のときのみ1、aとbのどちらかが0のときのみ0
^ ビット単位の XOR 低い a^b a と b が異なる場合、結果は 1 になり、a と b が同じ場合、結果は 0 になります。
l ビット単位または 最低 アルブ a と b のどちらか一方だけが 1 の場合、結果は 1 になります; a と b のみが同時に 0 の場合、結果は 0 です。
  • 割り当て番号と組み合わせて

これらの 4 つの演算子は、ビット単位の反転にはオペランドが 1 つしかないことを除いて、他の 3 つをコピー (=) と組み合わせることができるため、コードはより簡潔になります。

  • シフト演算子

変数内のすべてのビットを左または右にシフトします。

  • 左シフト演算子 (<<)

例: 11001010 << 2ここに画像の説明を挿入

  • 右シフト演算子 (>>)

例: 11001010 >> 2
ここに画像の説明を挿入

左シフト、右シフト演算子右オペランドが負の場合、また右のオペランドが、左のオペランドでサポートされる最大幅よりも大きいの場合、式の結果は "未定義の動作

左側のオペランドが符号付きか符号なしかは、実際にはシフト演算子に異なる影響を与えます。この時点では、変数のすべてのビットが値のサイズを表すために使用されるため、符号なしの数値は間違いなく問題ありません。ただし、符号付きの数値の場合は、別の方法で処理する必要があります。符号付き数値の左側の最初のビットは符号ビットです、したがって、オペランドがたまたま負の数である場合、シフト後に符号ビットを上書きする決定は依然としてコンパイラーに委ねられます。

  • 割り当て番号と組み合わせることができます

例えば:

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

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

ファイルの書き込みと書き出し

  • 1 文字の読み書き

読み取り: fgetc および getc
書き込み: fputc および putc

  • 文字列全体を読み書きする

読み取り: fgets
書き込み: fputs

  • バイナリの読み書きファイル

読み取り: fread
書き込み: fwrite

おすすめ

転載: blog.csdn.net/qq_44921056/article/details/119141480