記事ディレクトリ
- 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 #
}
int *funB(int num)
{
printf("%d\t", num);
return #
}
int *funC(int num)
{
printf("%d\t", num);
return #
}
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