1. 程式人生 > >自定義型別:結構體

自定義型別:結構體

一、 結構體宣告

struct tag//結構體型別名稱
{
   member-list;//成員變數
}variable-list;//結構體變數
  1. 省略結構體型別名稱(匿名結構體型別)
    當省略掉結構體型別名稱時,就不能省略掉結構體變數,這樣是不合理的,所以一般我們不建議省略結構體型別名
struct  
{
   int a;
   int b;
}x,y;//全域性變數
struct  
{
   int a;
   int b;
}a[20],*p;
int main()
{
  p=&x;//不合法程式碼
  return 0;
 }

注意:對於結構體而言,即使兩個結構體成員完全一樣,但依然是兩種型別,其定義的變數不能互相指向


注意:一個結構體只能指向自身結構體型別所定義的變數
2.省略結構體變數
完全可以,如下段程式碼:

struct  A
{
   int a;
   int b;
};
int main()
{
  struct A s;
  retuurn 0;//區域性變數
}

二.結構體成員

結構體成員可以是變數、陣列、指標、甚至其他結構體成員

  1. 結構體成員訪問
    結構體變數訪問成員 通過點操作符(.)訪問
    結構體指標訪問成員通過指向操作符(->)訪問
struct  A
{
   char name[10];
   int b;
};
int main()
{
    struct
A x; struct A *p; p=&x; x.a=10; (*P).a=20; p->name[1]='a'; return 0; }

三、結構體的自引用

如下段程式碼,這樣的結構體自引用是錯誤的,因為定義一個變數必先開闢空間,而我們不知道struct A的空間大小

struct  A
{
    char name[10];
    int b;
    struct  A obj;
};

如果我們非要自己應用自己呢?
如下段程式碼,是正確的結構體自引用方式,要自引用就必須引用自身變數的指標(因為指標不管是什麼型別都佔四個位元組大小的空間)

struct  A
{
    char name[10];
    int b;
    struct  A *obj;
};

注意,如下程式碼
typedef關鍵字是定義一個新的型別。
當typedef定義結構體時,結構體被定義後才能使用,如下兩段程式碼(第一段錯誤程式碼,第二段正確程式碼):

typedef struct  
{
    char name[10];
    int b;
    node *obj;
}node;
typedef struct  node
{
    char name[10];
    int b;
    node *obj;
}node;//node代表一種型別

四、結構的不完整宣告

struct B;//不完整宣告
struct A
{
    int a;
    struct B *pb;
};
struct B
{
    int b;
    struct A  *pb;
};

五、結構體變數的定義和初始化

結構體變數的初始化和陣列的初始化是一樣的只允許集體初始化,但是不允許集體賦值

#include<stdio.h>
struct Point
{
    int x;
    int y;
}p1;//宣告型別的時候同時定義變數p1
struct Node
{
    int data;
    struct Point p;
    struct Node *next;
};
int main()
{
    struct Point p2;//定義結構體變數p2
    struct Point p3 = { 1, 2 };//初始化:定義變數的同時賦值
    struct Node n1 = { 20, { 5, 6 }, NULL };//結構體巢狀初始化
    struct Node n2;
    //n2 = { 20, { 5, 7 }, NULL };//錯誤程式碼(結構體不可以被整體賦值)
    system("pause");
    return 0;
}

六、結構體記憶體對齊

對結構體瞭解到這裡,你一定很好奇怎麼計算結構體的大小,這個時候出現了結構體記憶體對齊問題,為什麼會出現記憶體對齊呢?感興趣的同學可以自己百度瞭解一下,下來我們來看一看。
結構體對齊規則:

  1. 第一個成員在與結構體變數偏移量為0的地址處
  2. 其他成員變數要對齊到某個數字(對齊數)的整數倍的地址處。對齊數=編譯器預設的一個對齊數和成員大小中的較小值。(vs中預設值為8,Linux預設值為4)
  3. 結構體總大小為最大對齊數(每個成員都有一個對齊數)的整數倍
  4. 如果嵌套了結構體的情況,巢狀的結構體對齊到自己的最大對齊數的整數被處,結構體的整數大小就是所有最大對齊數(含巢狀結構體的對齊數)的整數倍。
#include<stdio.h>
#pragma pack(8)//設定預設對齊數
struct S1
{
    char c1;
    int i;
    char c2;
};
int main()
{
    printf("%d\n", sizeof(struct S1));
    system("pause");
    return 0;
}

這裡寫圖片描述
這裡寫圖片描述

#include<stdio.h>
#pragma pack(8)//設定預設對齊數
struct S1
{
    double d;
    char c;
    int i;
};
struct S2
{
    char c1;
    struct S1 s1;//最大對齊數是8
    double d;
};
int main()
{
    printf("%d\n", sizeof(struct S2));
    system("pause");
    return 0;
}

這裡寫圖片描述
這裡寫圖片描述