結構體和多維數組的理解

C/C+++結構體和多維數組的理解,但願你們批評指正。數組

結構體

本質

其實就可能夠看作是一個普通類型(int),作函數參數時,也是值得傳遞。函數

定義和使用

struct x1 { ...};    和   typedef struct { ...} x2;   struct x1 { ...}para1,para2;佈局

區別 :  第一種形式聲明瞭一個 「結構標籤」;spa

            第二種聲明瞭一個 「類型定義」。指針

            第三種是定義了2個結構的變量1和變量2。code

            主要的區別是在後文中你須要用 「struct x1」 引用第一種, 而用 「x2」 引用第二種。也就是說, 第二種聲明更像一種抽象類新 —– 用戶沒必要知道它是一個結構, 而在聲明它的實例時也不須要使用struct 關鍵字。內存

內存大小

爲了提升CPU的存儲速度,VC對一些變量的起始地址作了「對齊」處理。編譯器

一、在默認狀況下,VC規定各成員變量存放的起始地址相對於結構的起始地址的偏移量必須爲該變量的類型所佔用的字節數的倍數string

二、VC爲了確保結構的大小結構的字節邊界數(即該結構中佔用最大空間的類型所佔用的字節數)的倍數,因此在爲最後一個成員變量申請空間後,還會根據須要自動填充空缺的字節。io

#include <stdio.h>
#include <string.h>

typedef struct
{
	char d1;
	char d2[5];
	int d3;
}dog;    // size 12,結構成員是數組,則類型爲數組元素的類型
typedef struct
{
	int c1;
	char c2[5];
	int c3;
}cat;	// size 16,結構成員是數組,則類型爲數組元素的類型

int main(int argc, char *argv[])
{
	dog dd;
	cat cc;
	printf("size of dog:%d\nsize of cat:%d\n",sizeof(dd),sizeof(cc));	
}

類型         對齊方式(變量存放的起始地址相對於結構的起始地址的偏移量) 

Char 偏移量必須爲sizeof(char)即1的倍數 

int 偏移量必須爲sizeof(int)即4的倍數 

float 偏移量必須爲sizeof(float)即4的倍數 

double 偏移量必須爲sizeof(double)即8的倍數 

Short 偏移量必須爲sizeof(short)即2的倍數 

初始化(總體)

struct s
{
    int   l;
    char* p;
};
 
int main(int argc, char* argv[])
{
    struct s s1 = {.l=4, .p = "abcd"};
    struct s s2 = {l:4, p:"abcd"};
 
    return 0;
}

結構體注意

一、結構體中嵌套第三方提供的DLL庫中的結構體時,須要從新編譯相關的代碼。

struct base
{
    int n;
};
 
struct s
{
    struct base b;
    int m;
};

如今假設第一個結構是第三方提供的,第二個結構是你本身的。第三方提供的庫是以DLL方式分發的,DLL最大好處在於能夠獨立替換。但隨着軟件的進化,問題可能就來了。

當第三方在第一個結構中增長了一個新的成員int k;,編譯好後把DLL給你,你直接給了客戶了。程序加載時不會有任何問題,在運行邏輯可能徹底改變!緣由是兩個結構的內存佈局重疊了。解決這類錯誤的惟一辦法就是所有從新編譯相關的代碼

數組

數組名和&數組名區別

數組名的值只是一個指針常量不能被修改(指針的值),數組名錶示數組的首元素地址(等價與&數組名[0]),對數組的數組名作&操做則是整個數組的地址

eg:

int arrys[10] = {0};
printf("arrys:%d    arrys+1:%d \n",arrys,arrys+1);
printf("&arrys:%d   &arrys+1:%d \n",&arrys,&arrys+1);

輸出:
arrys:2293520    arrys+1:2293524
&arrys:2293520   &arrys+1:2293560

多維數組的數組名和&數組名理解:

一維數組數組名     數組的首元素首地址 ,&數組名     整個數組的首地址

多維數組: 數組名     一維數組的首地址 ,&數組名     整個數組的首地址

證實以下:

一維數組 數組名     數組的首元素首地址 ,&數組名     整個數組的首地址

int main(int argc, char *argv[])
{
	int arr1[2];
	printf("arr1:%d    arr1+1:%d\n",arr1,arr1+1); 
	printf("&arr1:%d    &arr1+1:%d\n",&arr1,&arr1+1); 	
}

    輸出:

    arr1:2686784    arr1+1:2686788                      相差:4字節

    &arr1:2686784    &arr1+1:2686792                相差:8字節=2*4

二維數組: 數組名     一維數組的首地址 ,&數組名     整個數組的首地址

int main(int argc, char *argv[])
{
	int arr1[2][3];
	printf("arr1:%d    arr1+1:%d\n",arr1,arr1+1); 
	printf("&arr1:%d    &arr1+1:%d\n",&arr1,&arr1+1); 	
}

    輸出:

    arr1:2686752    arr1+1:2686764                      相差:12字節=3*4

    &arr1:2686752    &arr1+1:2686776                相差:24字節=2*3*4

三維數組: 數組名     一維數組的首地址(包含後面的二維和三維數組) ,&數組名     整個數組的首地址

int main(int argc, char *argv[])
{
	int arr1[2][3][4];
	printf("arr1:%d    arr1+1:%d\n",arr1,arr1+1); 
	printf("&arr1:%d    &arr1+1:%d\n",&arr1,&arr1+1); 	
}

    輸出:

    arr1:2686688    arr1+1:2686736                    相差:48字節=3*4*4

    &arr1:2686688    &arr1+1:2686784              相差:96字節=2*3*4*4

四維數組: 數組名    一維數組的首地址(包含後面的二維、三維和四維數組)  ,&數組名     整個數組的首地址

int main(int argc, char *argv[])
{
	int arr1[2][3][4][5];
	printf("arr1:%d    arr1+1:%d\n",arr1,arr1+1); 
	printf("&arr1:%d    &arr1+1:%d\n",&arr1,&arr1+1); 	
}

    輸出:

    arr1:2686304    arr1+1:2686544                      相差:240字節=3*4*5*4

    &arr1:2686304    &arr1+1:2686784                相差:480字節=2*3*4*5*4

N維數組: 數組名     一維數組的首地址(包含後面的二維、三維......N-1維數組) ,&數組名     整個數組的首地址

 

數組參數等效的指針參數理解:

        數組參數                            等效的指針參數

一維數組 char a[30]                    指針:char *a

指針數組 char *a[30]                  指針的指針:char **a

二維數組char a[10][30]              數組的指針:char (*a)[30]

 

數據類型 * 指針名  其實就是告訴編譯器,這個指針指向一個什麼數據類型的內存,在對指針操做時,能夠知道其指向的內存佔用多少內存,可是指針自己是4個字節(sizeof)。

相關文章
相關標籤/搜索