技術共有

C言語 - 構造

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

1. 構造を定義して使用する

1.1 概要

これまでに見た int、float、char などのデータ型は、プログラム内で単に使用されているだけですが、必要に応じて複雑なデータを作成したい場合は、構造体を使用する必要があります。

たとえば、生徒の学籍番号、名前、性別、年齢などは同じ生徒に属しますが、これらの変数は異なる型に属しており、単に異なる変数を使用して単純に定義すると、それらの間の関係を反映することが困難になります。 . 内部のつながり。次に、これらのデータを結合できる変数を作成し、それを変数に入れると、より簡単に使用できるようになります。これが構造の学習です。

  1. 结构体类型:
  2.         struct Student
  3.         {
  4.               int num;//学号为整形;
  5.               char name[20];//姓名为字符串;
  6.               char sex;//性别为字符型;
  7.               int age;//年龄为整形
  8.               float score;//成绩为浮点型
  9. char addr[30];//地址为字符型;
  10. }

で:

struct Student は構造体の型です。

struct は構造体の型を宣言するキーワードです。

Student は、他の構造と区別するための構造の名前です。

中括弧には構造体のメンバーが含まれており、そのグループはメンバー リストと呼ばれ、その名前は変数の名前と一致します。

注: 構造体のタイプには次のような複数のタイプがあります。

構造体のメンバーは、別の構造体の型になることもできます。

構造体日付

{        

整数 月;

int 日;

整数年;

};

構造体学生

{

整数 数値;

文字名[20];

char セックス;

年齢;

構造体 Date 誕生日;

文字アドレス[30];

}

1.2 構造体変数の定義

先ほどは、モデルに相当する構造体の型のみを定義し、変数は定義しませんでした。次に、構造体変数を定義し、そこに特定のデータを格納します。3 つのメソッド。

方法 1: 最初に構造体の型を宣言し、次に構造体の変数を定義する

前の構造体タイプ struct Student に基づいて、構造体変数を定義します。

構造体 Student 学生1、学生2;

このメソッドは int a,b と似ていますが、唯一の前提条件は、構造体型がすでに存在し、その型に基づいて構造体変数が定義されていることです。

    方法 2: 型を宣言しながら変数を定義する

形状:

struct 構造名

                {

メンバーリスト;

}変数名のリスト;

例:

構造体学生
                {
整数 数値;
文字名[20];
char セックス;
年齢;
フロートスコア;
文字アドレス[30];
}学生1、学生2;

      方法 3: 型名を指定せずに構造体型変数を直接定義する

形状:

構造体

                        {

メンバー変数。

}変数名のリスト;

これは名前のない構造タイプであり、一般的には使用されません。

注: 1. 構造体変数のメンバー名は、プログラム内の変数名と同じにすることができます。

2. 構造体変数のメンバーは単独で使用でき、その状態と機能は通常の変数と同等です。

1.3 構造体変数の初期化と参照

構造体変数を定義するときに初期化します。

      例:学生の情報(学籍番号、名前、性別、住所など)を構造体変数に入れて出力します。

  1. #include <stdio.h>
  2. int main()
  3. {
  4. struct Student
  5. {
  6. int num;
  7. char name[20];
  8. char sex;
  9. char addr[20];
  10. }student1 = {101,"Li li",'M',"123XiAn"};
  11. printf("NO:%d,nname:%snssex:%cnaddress:%sn",student1.num,student1.name,student1.sex,student1.addr);
  12. return 0;

結果分析:

構造体変数を定義するときは、そのメンバーを初期化します。初期化リストは、中括弧で囲まれた多数の定数です。これらの定数は、構造体変数の初期化ではなく、一度に構造体変数に割り当てられます。ボディタイプの初期化。

構造体変数のメンバーの値、参照方法は次のとおりです。

構造体変数名.メンバー名

学生1の名前

      別の構造体タイプに属する構造体メンバーの場合、最下位レベルのメンバーはレベルごとに検索する必要があります。たとえば、上記の構造体 Student には、構造体 Date Birthday が含まれています。

生徒の誕生日.月

同じタイプの構造体を相互に割り当てることができます。学生1=学生2;

        例:2人の学生の学生ID、名前、成績を入力し、成績の高い学生の学生ID、名前、成績を出力します。

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. int main()
  4. {
  5. struct Student
  6. {
  7. int num;
  8. char name[20];
  9. float score;
  10. }student1,student2;
  11. scanf("%d%s%f", &student1.num, student1.name, &student1.score);
  12. scanf("%d%s%f", &student2.num, student2.name, &student2.score);
  13. printf("The higher score is:n");
  14. if (student1.score > student2.score)
  15. {
  16. printf("%d %s %6.2fn", student1.num, student1.name, student1.score);
  17. }
  18. else if (student1.score < student2.score)
  19. {
  20. printf("%d %s %6.2fn", student2.num, student2.name, student2.score);
  21. }
  22. else
  23. {
  24. printf("%d %s %6.2fn", student1.num, student1.name, student1.score);
  25. printf("%d %s %6.2fn", student2.num, student2.name, student2.score);
  26. }
  27. }

scanf 関数を使用して構造体変数を入力する場合、scanf 関数内で構造体変数名を使用してすべてのメンバーの値を一度に入力することはできません。scanf 関数の前に & がないことに注意してください。配列名はもともと「住所を取得しました」を表すためです。

2. 構造体配列を使用する

2.1 構造体配列の定義

先ほど構造変数を定義したときは、1つずつ定義しましたが、操作に参加する必要がある関連データのグループである場合、当然、10人の生徒の情報を使用する必要があります。は構造体配列であり、構造体配列の各配列要素は構造体です。

例: 候補者が 3 人いて、各投票者は 1 人にのみ投票できます。まず、候補者の名前を入力し、最後に各人の投票結果を表示するプログラムを作成する必要があります。

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <string.h>
  4. struct Person
  5. {
  6. char name[20];
  7. int count;
  8. }leader[3] = { "wang", 0, "zhang", 0, "li", 0 };
  9. int main()
  10. {
  11. int i, j;
  12. char lead_name[20];
  13. for (i = 0; i < 10; i++)
  14. {
  15. scanf("%s", lead_name);
  16. for (j = 0; j < 3; j++)
  17. {
  18. if (strcmp(lead_name, leader[j].name) == 0)
  19. leader[j].count++;
  20. }
  21. }
  22. printf("nResultn");
  23. for (i = 0; i < 3; i++)
  24. {
  25. printf("name:%s,count:%dn", leader[i].name, leader[i].count);
  26. }
  27. return 0;
  28. }

構造体配列の一般的な形式を定義します。

        struct 構造名

        {

変数リスト

配列名 [配列長];

または

まず構造体タイプ (struct Student など) を宣言し、次に構造体配列を定義します。

        構造体型配列名 [配列長];

構造体配列を初期化する形式は、定義の後に次のように追加します。

      ={初期値リスト};     

2.2 構造体配列の使用

        例:n 人の生徒に関する情報 (学生 ID、名前、成績を含む) があり、各生徒の情報を成績順に出力する必要があります。

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <string.h>
  4. struct Student
  5. {
  6. int num;
  7. char name[20];
  8. float score;
  9. };
  10. int main()
  11. {
  12. struct Student stu[5] = { 1001, "Wangwei", 98.25, 1002, "Liuliu", 91, 1003, "Zhangli", 98, 1004, "Xiaozhao", 85, 1005, "Baibai", 94 };
  13. struct Student temp;
  14. printf("The order id:n");
  15. int i, j,k;
  16. for (i = 0; i < 4; i++)
  17. {
  18. k = i;
  19. for (j = i + 1; j < 5; j++)
  20. {
  21. if (stu[j].score>stu[k].score)
  22. {
  23. k = j;
  24. }
  25. }
  26. temp = stu[k];
  27. stu[k] = stu[i];
  28. stu[i] = temp;
  29. }
  30. for (i = 0; i < 5; i++)
  31. {
  32. printf("%d %s %5.2f", stu[i].num, stu[i].name, stu[i].score);
  33. printf("n");
  34. }
  35. return 0;
  36. }

3. 構造体ポインタ

3.1 構造体変数へのポインタ

いわゆる構造体ポインタは、構造体変数へのポインタです。構造体変数の開始アドレスは、構造体変数のポインタです。

構造体オブジェクトを指すポインター変数は、構造体変数または構造体配列の要素のいずれかを指すことができます。ポインター変数の基本型は、構造体変数の型と同じである必要があります。

例: struct Student * pt;

例:構造体変数を指すポインタ変数を通じて、構造体変数内のメンバーの情報を出力します。

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <string.h>
  4. struct Student
  5. {
  6. long num;
  7. char name[20];
  8. char sex;
  9. float score;
  10. };
  11. int main()
  12. {
  13. struct Student stu1;
  14. struct Student *pt;
  15. pt = &stu1;
  16. stu1.num = 10001;
  17. strcpy(stu1.name, "Lili");
  18. stu1.sex = 'M';
  19. stu1.score = 96.5;
  20. printf("No:%dnname:%snsex:%cnscore:%5.1fn", stu1.num, stu1.name, stu1.sex, stu1.score);
  21. printf("n");
  22. printf("No:%dnname:%snsex:%cnscore:%5.1fn", (*pt).num, (*pt).name, (*pt).sex, (*pt).score);
  23. printf("n");
  24. printf("No:%dnname:%snsex:%cnscore:%5.1fn", pt->num, pt->name, pt->sex, pt->score);
  25. return 0;
  26. }

結果分析:

この関数では、最初の printf 関数は構造体変数名 stu1 を通じてメンバーにアクセスします。

2 番目の printf 関数は、構造体変数を指すポインター変数を介してそのメンバーにアクセスします。(*pt) は指す構造体変数を表し、(*pt).num は指す構造体メンバーを表します。

さらに、C 言語では、(*pt).num を pt-&gt;num に置き換えることができます。

3.2 構造体配列へのポインタ

ポインター変数を使用して、構造体配列の要素を指すことができます。

例:構造体配列には 3 人の生徒の情報があり、生徒の情報を出力する必要があります。

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <string.h>
  4. struct Student
  5. {
  6. long num;
  7. char name[20];
  8. char sex;
  9. float score;
  10. };
  11. int main()
  12. {
  13. struct Student stu[3] = { 1001, "wangle", 'M', 95, 1002, "chengcai", 'M', 99.9, 1003, "shangmin", 'F', 85.2 };
  14. struct Student *pt;
  15. printf("No. name sex scoren");
  16. for (pt = stu; pt < stu + 3; pt++)
  17. {
  18. printf("%d %s %c %5.2fn", pt->num, pt->name, pt->sex, pt->score);
  19. }
  20. return 0;
  21. }

プログラムでは、pt は struct Student 型の構造体変数へのポインタです。pt=stu[1].name は構造体の特定のメンバーを指すのではなく、構造体変数を指すために使用されます。もう 1 つは構造体変数、もう 1 つは構造体メンバー変数です。 p++ の場合、p の値により構造の長さが増加します。

3.3 構造体変数と構造体変数へのポインタを関数のパラメータとして使用する

構造体変数の値を関数に渡す方法は 3 つあります。

1. 構造体変数のメンバーをパラメーターとして使用する このメソッドは、仮パラメーターと実パラメーター (構造体メンバー) が同じ型であることに注意してください。

2. 構造体変数を実パラメータとして使用します。構造体変数が実パラメータとして使用される場合、その構造体変数が占有するメモリ ユニットのすべての内容も仮パラメータに渡されます。

3. 構造体変数(配列)へのポインタを実引数として、構造体変数(配列)のアドレスを仮引数に渡します。

例:

学生の学生ID、氏名、3コースの成績などn個の構造があります。 平均成績の上位の学生の情報(学生ID、氏名、3コースの成績、平均成績など)を出力する必要があります。 。

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <string.h>
  4. void print(struct Student stud);
  5. struct Student Max(struct Student stu[]);
  6. void input(struct Student stu[]);
  7. struct Student
  8. {
  9. int num;
  10. char name[20];
  11. float score[3];
  12. float aver;
  13. };
  14. int main()
  15. {
  16. struct Student stu[3], *pt;
  17. pt = stu;
  18. input(pt);
  19. print(Max(pt));
  20. return 0;
  21. }
  22. void input(struct Student stu[])
  23. {
  24. int i;
  25. printf("请输入各学生的信息:学号、姓名、3门成绩:n");
  26. for (i = 0; i < 3;i++)
  27. {
  28. scanf("%d%s%f%f%f", &stu[i].num, stu[i].name, &stu[i].score[0], &stu[i].score[1], &stu[i].score[2]);
  29. stu[i].aver = (stu[i].score[0] + stu[i].score[1] + stu[i].score[2]) / 3.0;
  30. }
  31. }
  32. struct Student Max(struct Student stu[])
  33. {
  34. int i, m = 0;
  35. for (i = 0; i < 3; i++)
  36. {
  37. if (stu[i].aver > stu[m].aver)
  38. m = i;
  39. }
  40. return stu[m];
  41. }
  42. void print(struct Student stud)
  43. {
  44. printf("成绩最好的学生是:n");
  45. printf("学号:%d 姓名:%s 三门课程:%5.2f %5.2f %5.2f平均成绩:%5.2fn", stud.num, stud.name, stud.score[0], stud.score[1], stud.score[2], stud.aver);
  46. }

1. 入力関数を呼び出す場合、実パラメータはポインタ変数 pt であり、仮パラメータは構造体要素の開始アドレスであり、関数には戻り値がありません。

2. Max関数を呼び出す場合、実引数はポインタ変数pt、仮引数は構造体配列、構造体要素の開始アドレスが渡され、関数の戻り値は構造体型データとなります。

3. print関数を呼び出す場合、実引数は構造体変数(構造体配列要素)、仮引数は構造体変数の各メンバの値が渡され、戻り値はありません。

4. リンクリスト

4.1 概要

リンク リストは一般的なデータ構造であり、動的ストレージ割り当てのための構造です。

データを配列に格納する場合、100 人の生徒がいるクラスと 30 人の生徒がいるクラスがある場合、異なるクラスの生徒のデータを同じ配列に格納する場合、配列の長さ (複数の配列) を事前に定義する必要があります。長さ 100 の配列を定義する必要がありますが、リンクされたリストには、必要に応じてメモリ ユニットが解放されるという欠点がありません。

リンク リストには、図の head で表される「ヘッド ポインタ」変数があり、要素を指すアドレスが格納されます。リンク リストの各要素は「ノード」と呼ばれ、各ノードには次の 2 つの部分が含まれます。

1. ユーザーが必要とする実際のデータ。

2. 次の要素のアドレス。

メモリ内のリンク リスト内の各要素のアドレスが不連続であることがわかります。特定の要素を見つけるには、まず前の要素を見つける必要があり、前の要素のアドレスに基づいて次の要素を見つけることができます。 。 「ヘッド ポインタ」が指定されていない場合、リンクされたリスト全体にアクセスできません。

この場合、構造体を使用してリンク リストを構築するのが最も適切です。構造体には複数のメンバーが含まれており、ポインタ タイプのメンバーは次のノードのアドレスを格納するために使用されます。

構造体学生

        {

整数 数値;

整数スコア;

構造体 Student *next;

        }

このうち、numとscoreはユーザーデータの格納に使用され、nextは次のノードのアドレスの格納に使用されます。

4.2 静的リンクリスト

場合:

3 人の生徒のデータを含むノードで構成される静的リンク リストを作成し、各ノードのデータを出力するように要求します。

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. struct Student
  4. {
  5. int num;
  6. float score;
  7. struct Student * next;
  8. };
  9. int main()
  10. {
  11. struct Student a, b, c, *head, *p;
  12. a.num = 1001; a.score = 85.5;
  13. b.num = 1002; b.score = 95.5;
  14. c.num = 1003; c.score = 84.5;
  15. head = &a;
  16. a.next = &b;
  17. b.next = &c;
  18. c.next = NULL;
  19. p = head;
  20. do
  21. {
  22. printf("%d %5.2fn", p->num, p->score);
  23. p = p->next;
  24. } while (p != NULL);
  25. return 0;
  26. }

たとえば、head がノード a を指し、a.next がノード b を指し、b.next がノード c を指し、c.next が null を指すようにリンク リストを作成します。これにより、リンク リスト関係が形成されます。

リンク リストを出力する場合は、まず p を使用し、p が a を指すようにしてから、p=p-&gt;next で次のノードの出力を準備する必要があります。

4.3 動的リンクリスト

4.3.1 動的メモリ割り当て

動的リンク リストについて説明する前に、まず動的メモリ割り当てについて説明します。

先ほど、変数はグローバル変数とローカル変数に分けられると述べました。グローバル変数はメモリの静的ストレージ領域に割り当てられ、非静的に格納されるローカル変数はメモリの動的ストレージ領域に割り当てられます。この記憶領域をメモリと呼びます。スタック

さらに、C 言語では、一時データを保存するための動的メモリ割り当て領域を確立することもできます。これらのデータは、必要なときに開かれ、不要になったときに一時的に解放される、この保存領域と呼ばれます。ヒープ

メモリの動的な割り当ては、システムが提供する関数 (malloc、calloc、free、realloc 関数) によって実現されます。

1. malloc 関数を使用して動的ストレージ領域を開きます。

関数: void *malloc (符号なし整数サイズ);

関数:

        メモリの動的記憶領域に長さサイズ(単位:バイト)の連続した空間を確保します。

戻り値:

最初に割り当てられたバイトのアドレスには型はなく、単なるプレーンなアドレスです。

2. calloc 関数を使用して動的ストレージ領域を開きます。

関数:void * calloc(unsigned n,unsigned size);

関数:

メモリの動的記憶領域に、size の長さの n バイトの連続領域を割り当てます。このスペースは、配列を保存するのに十分な比較的大きなサイズです。

calloc 関数を使用して、1 次元配列の動的記憶領域を開きます。n は配列要素の数、size は要素の長さです。

戻り値:

最初に割り当てられたバイトのアドレスには型はなく、単なるプレーンなアドレスです。

3. realloc 関数を使用して動的ストレージ領域を再割り当てします。

関数:void * realloc(void *p 、unsigned int サイズ);

関数:

割り当てられた動的メモリを再割り当てします。

関数recalllocを使用して、pが指す動的空間のサイズをsizeに変更します。 p の値は変更されません。

戻り値:

更新後の動的メモリの最初のバイトのアドレスは、基本的に p が指すアドレスになります。

4. free関数を使用して動的記憶領域を解放する

関数: void を解放します(void *p);

関数:

ポインタ変数 p が指す動的空間を解放し、空間のこの部分を他の変数で使用できるようにします。

p は、malloc 関数と calloc 関数の最新の呼び出しから取得された戻り値です。

戻り値:

なし;

注記注: 上記 4 つの関数の宣言はすべて stdlib.h ヘッダー ファイルにあります。

ボイドポインタ型:

上記の関数 malloc 関数と calloc 関数の戻り値は両方とも void * 型です。これは、任意の型を指しているのではなく、空の型を指していることを意味します。または、特定の種類のデータを指していません。

動的メモリを呼び出すとき、プログラムは関数によって返された純粋なアドレスのみを使用し、このアドレスを使用したい場合は、データ型を指す属性を使用しません。

例えば:

int *p;

p = (int*)malloc(100);

場合:

動的データを作成し、5 人の生徒のスコアを入力し、関数を使用して 60 点未満の生徒がいるかどうかをチェックし、不適格なスコアを出力します。

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. int main()
  5. {
  6. void check(int * p);
  7. int *p1, i;
  8. p1 = (int *)malloc(5 * sizeof(int));
  9. for (i = 0; i < 5; i++)
  10. {
  11. scanf("%d", p1 + i);
  12. }
  13. check(p1);
  14. return 0;
  15. }
  16. void check(int * p)
  17. {
  18. int i;
  19. printf("they are fail:n");
  20. for (i = 0; i < 5; i++)
  21. {
  22. if (*(p+i) < 60)
  23. printf("%d ", *(p + i));
  24. }
  25. }

操作結果:

結果分析:

プログラム内では配列は定義されていませんが、動的空き割り当て領域が解放されて配列として使用されます。

malloc 関数では、動的領域を割り当てるために特定の値は直接渡されません。代わりに、sizeof を使用してシステム整数のバイト数が計算され、5 つの要素が作成されます。 p を使用して最初のバイト アドレスを指し、それを int 型に変換します。p+1 は次の要素を指します。

4.3.2 ダイナミックリンクリストの作成

4 人の生徒のデータを含む動的リンク リストを作成する関数を作成します。

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #define LEN sizeof(struct Student)
  5. struct Student
  6. {
  7. long num;
  8. float score;
  9. struct Student * next;
  10. };
  11. int n;
  12. struct Student * creat(void)
  13. {
  14. struct Student * head, *p1, *p2;
  15. n = 0; p1 = p2 = malloc(LEN);
  16. scanf("%ld%f", &p1->num, &p1->score);
  17. head = NULL;
  18. while (p1->num != 0)
  19. {
  20. n = n + 1;
  21. if (n == 1)
  22. head = p1;
  23. else p2->next = p1;
  24. p2 = p1;
  25. p1 = (struct Student *)malloc(LEN);
  26. scanf("%ld%f", &p1->num, &p1->score);
  27. }
  28. p2->next = NULL;
  29. return (head);
  30. }
  31. int main()
  32. {
  33. struct Student * pt;
  34. pt = creat();
  35. printf("n num:%ld score:%5.2fn", pt->num, pt->score);
  36. return 0;
  37. }

操作結果:

結果分析: 動的リンク リストを作成するには、最初に 3 つの構造体ポインターを指定し、次に malloc 関数を使用してノードを作成します。次に、p1 が malloc 関数を使用してノードを作成し、次に p2 を使用します。 p2=p1 をポイントした後、p1 は p2 を作成します。次に、p1 の要素の値が 0 になるまで、p2=p1 をポイントします。新しく作成されたノードは NULL を指します。このようにして、先頭が最初のノードを指します。これが先頭ノードです。

動的リンクリストの入力と出力:

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #define LEN sizeof(struct Student)
  5. struct Student
  6. {
  7. long num;
  8. float score;
  9. struct Student * next;
  10. };
  11. int n;
  12. struct Student * creat(void)
  13. {
  14. struct Student * head, *p1, *p2;
  15. head = NULL;
  16. n = 0;
  17. p2 = p1 = malloc(LEN);
  18. scanf("%ld%f", &p1->num, &p1->score);
  19. while (p1->num != 0)
  20. {
  21. n = n + 1;
  22. if (n == 1)
  23. head = p1;
  24. else
  25. p2->next = p1;
  26. p2 = p1;
  27. p1 = malloc(LEN);
  28. scanf("%ld %f", &p1->num, &p1->score);
  29. }
  30. p2->next = NULL;
  31. return head;
  32. }
  33. void print(struct Student * p)
  34. {
  35. do
  36. {
  37. printf("%ld %5.2fn", p->num ,p->score);
  38. p=p->next;
  39. } while (p->num != NULL);
  40. }
  41. int main(void)
  42. {
  43. struct Student * pt;
  44. pt = creat();
  45. print(pt);
  46. return 0;
  47. }

操作結果:

5.ユニオンタイプ

5.1 概要

たとえば、整数変数、文字変数、および浮動小数点変数を同じアドレスから始まるメモリ ユニットに配置することで、複数の変数が同じメモリ ユニットを共有できるようになります。メモリ構造のセクションは「ユニオン」と呼ばれます。

共用体の一般的な形式を定義します。

労働組合名

        {

メンバーリスト;

変数リスト;

例えば:

ユニオンデータ

        {

整数 i;

文字 ch;

フロートf;

}a、b、c;

構造体変数が占有するメモリ長は各メンバーが占有するメモリ長の合計ですが、共用体が占有するメモリ長は最も長いメンバーの長さになります。

5.2 引用

参照できるのは、事前に定義されている共用体変数のみです。参照しているのは共用体変数ではなく、参照されている共用体変数のメンバーであることに注意してください。

ai は共用体変数内の整数変数を指します。

a.ch は共用体変数内の文字変数を参照します。

af は共用体変数の実数変数を参照します。

5.3 特徴

1. メモリ セグメントは、いくつかの異なるタイプのメンバーを格納するために使用できますが、同時に複数のメンバーを格納するのではなく、各瞬間に 1 つだけを格納できます。

2. ユニオン変数は初期化できますが、初期化テーブルに含めることができる定数は 1 つだけです。

3. 共用体変数のメンバは最後に割り当てられたメンバとなり、以前の元の変数は上書きされて置き換えられます。

4. 共用体変数のアドレスは、そのメンバのアドレスと同じです。

5. 共用体変数名に値を代入したり、変数名を参照して値を取得したりすることはできません。

6. 列挙型

一部の変数に取り得る値が少数しかない場合、それらを列挙型として定義できます。いわゆる列挙とは、取り得る値を 1 つずつ列挙するものです。

列挙型の宣言は、たとえば enum で始まります。

eunm 曜日{日、月、火、水、木、金、土};

上記は列挙型 enum Weekday を宣言しています。この型を使用して変数を定義できます。

enum 平日 平日、週末;

このうち、平日と週末は列挙変数として定義され、中括弧は列挙要素または列挙定数と呼ばれます。

列挙型を宣言する一般的な形式は次のとおりです。

enum [列挙名] {列挙要素リスト};

例:

ポケットの中には赤、黄、青、白、黒の 5 種類の小さなボールがあり、毎回袋から 3 つのボールを取り出し、異なる色の 3 つのボールを取得して配置する方法を尋ねます。

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. int main()
  4. {
  5. enum Color {red,yellow,bule,white,black};
  6. enum Color i, j, k, pri;
  7. int n, loop;
  8. n = 0;
  9. for (i = red; i <= black; i++)
  10. for (j = red; j <= black; j++)
  11. if (i != j)
  12. {
  13. for (k = red; k <= black; k++)
  14. if ((k != i) && (k != j))
  15. {
  16. n++;
  17. printf("%d ", n);
  18. for (loop = 1; loop <= 3; loop++)
  19. {
  20. switch (loop)
  21. {
  22. case 1:pri = i; break;
  23. case 2:pri = j; break;
  24. case 3:pri = k; break;
  25. default:break;
  26. }
  27. switch (pri)
  28. {
  29. case red:printf("%s ", "red"); break;
  30. case yellow:printf("%s ", "yellow"); break;
  31. case bule:printf("%s ", "bule"); break;
  32. case white:printf("%s ", "white"); break;
  33. case black:printf("%s ", "black"); break;
  34. default:break;
  35. }
  36. }
  37. printf("n");
  38. }
  39. }
  40. printf("n total:%dn", n);
  41. return 0;
  42. }

操作結果:

7. typedef を使用して新しい型名を宣言します

typedef を使用して、既存の型名を置き換える新しい型名を指定します。

1. 元のタイプ名を新しいタイプ名に置き換えるだけです。

例えば:

typedef int 整数;

typedef float 実数;

したがって、次の 2 行は同等です。

int i,j;———— 整数i、j;

2. 複雑な型表現方法の代わりに単純な型名を付ける

  構造体の型を表す新しい型名を付けます。

typedef構造体

        {

整数 mun;

                ......

} データ;

次に、新しい型名 Data を使用して変数を定義します。

データ誕生日;

データ * p;

      配列型の代わりに新しい型名を付けます。

typedef int 数値[100];

番号 a;

      ポインタ型を表す新しい型名を付けます。

typedef char * 文字列;

文字列p,a[10];

      関数へのポインターを表す新しい型名を付けます。

typedef int (* ポインタ)();

ポインタ p1,p2;

           概要: 変数の定義方法に従って、変数名を新しい型名に置き換え、先頭に typedef を追加して、新しい型名が元の型を表すことを宣言します。

typetef は既存の型の新しい型名を指定するだけで、新しい型は作成しません。

typetef と #define には表面的な類似点があります。

typedef int カウント

#define Count int

これらの機能は、int の代わりに Count を使用することですが、実際には、#define はコンパイル前に処理され、単純な文字列置換としてのみ使用できますが、typedef はコンパイル段階で処理されます。実際には単純な置き換えではありません。代わりに、新しい型名が生成され、変数が定義されます。