C語言基礎語法第十一篇

LoveHoneyYou 2022-01-08 03:00:18 阅读数:967

十一 一篇

為什麼我們需要柔性數組?

#define MAXLEN 1024
struct kd_node
{
struct kd_node*left;
struct kd_node*right;
int dim;
unsigned long long data[MAXLEN];
};

在這段代碼中,為了存儲數據,申請了長度為1024的unsigned long long型數組。若是數組長度遠遠小於MAXLEN。這樣設計,便會是極其浪費空間的。如果MAXLEN太小,我們需要的數組長度又很大,這樣也不合理。所以為了滿足我們的需求,便出現了柔性數組,也稱變長數組,可根據具體需求選擇大小,故而擁有為變長或柔性,這一誘人的特點~~~

柔性數組的廬山真面目

struct sd_node
{
int num;
int size;
char data[];
};

柔性數組是大小待定的數組

在C語言中,可以使用結構體產生柔性數組, 在結構體的設計中,最後一項為數組,且其長度為0(或者不給出長度),這個數組就是柔性數組

:全局數組或者局部數組不能這樣定義

柔性數組的細節

在strcut sd_node結構體中data,僅僅是一個標識符,不占用存儲空間。所以

sizeof(strcut sd_node)=   8

用途長度為0的數組主要是滿足長度可變的結構體

用法在結構體的最後,聲明一個長度為0的數組,就可以使得這個結構體是可變長的。對於編譯器來說,此時長度為0的數組並不占用空間,因為數組名本身不占用空間,它只是一個偏移量,數組名這個符號本身代錶了一個不可修改的地址常量。對於這個數組的大小,我們可以動態分配

int main()
{
const char str[] = "Hello Love_Hoeny_You";
struct sd_node*sp = (struct sd_node*)malloc(sizeof(struct sd_node) + 100);
sp->num = 5;
sp->size = 21;
strcpy(sp->data, str);
free(sp);
system("pause");
return 0;
}

圖解:

優點比起在結構體中聲明一個指針變量,在進行動態分配的方法,這種方法效率更高

指針數據包:

#include <stdlib.h>
#include <stdio.h>
struct data_buff
{
int num; //塊號
int size; //數據長度
char*data;
};
int main()
{
const char str[] = "Hello Love_Honey_You";
struct data_buff*ptr_buff = (struct data_buff*)malloc(sizeof(struct data_buff));
if (ptr_buff == NULL)
{
exit(1);
}
ptr_buff->size = strlen(str)+1;
ptr_buff->data = (char*)malloc(sizeof(char)*ptr_buff->size);
if (ptr_buff->data == NULL)
{
exit(1);
}
strcpy(ptr_buff->data, str);
printf("OVER\n");
free(ptr_buff->data);
free(ptr_buff);
ptr_buff = NULL;
system("pause");
return 0;
}

:釋放時要向釋放ptr_buff->data,再釋放ptr_buff。如果順序相反,則會丟掉ptr_buff->data內存儲的地址,造成內存泄漏。並且釋放了ptr_buff,再去釋放ptr_buff->data,編譯器會報錯~~~

變長數據緩沖區

#include <stdio.h>
#include <stdlib.h>
struct data_buff
{
int num; //塊號
int len; //數據長度
char data[];
};
int main()
{
const char str[] = "Love_Honey_You~~~";
struct data_buff*p_buff = (struct data_buff*)malloc(sizeof(struct data_buff) + sizeof(char)*(strlen(str) + 1));
if (p_buff == NULL)
{
exit(1);
}
strcpy(p_buff->data, str);
free(p_buff);
system("pause");
return 0;
}

缺點在結構體中,長度為0的數組必須在最後聲明,在設計結構體類型有一定限制 

如果結構體是通過 calloc,malloc或者realloc等動態分配方式生成,在不需要時要釋放相應的空間

sizeof 計算帶有柔性數組的結構體大小

#include <stdio.h>
#include <stdlib.h>
struct data_buff
{
int num;
int len;
char data[]; //data為標識符不占用空間
};
int main()
{
struct data_buff test = { 1, strlen(), "My_Love_Girl" }; //棧上的柔性數組
int len = sizeof(struct data_buff);
system("pause");
return 0;
}

sizeof計算的是數據類型所占的字節數,並且是在編譯時就確定了 

動態創建二維數組

#include <stdio.h>
#include <stdlib.h>
int main()
{
int cos = 0; //行
int row = 0; //列
scanf("%d%d", &cos, &row);
int**s = (int **)malloc(sizeof(int*)*cos);
for (int i = 0; i < cos; i++)
{
s[i] = (int *)malloc(sizeof(int)*row);
}
for (int i = 0; i < cos; i++)
{
for (int j = 0; j < row; j++)
{
s[i][j] = i + j;
printf("%d ", s[i][j]);
}
printf("\n");
}
for (int i = 0; i < cos; i++)
{
free(s[i]);
}
free(s);
system("pause");
return 0;
}

 

s裏存放的是指針數組中第一個元素的地址,指針數組中第一個元素存放的是第一行整型數組中第一個元素的地址,指針類型不同+1能力不同,通過下標運算符可方便訪問二維數組的每一個元素

舉個例子,在棧上創建數組 int  arr[3] [4]

arr[2][3]與s[2][3]的區別

(1)  &arr錶示整個二維數組的地址,而&s錶示的是存放指針數組中第一個元素地址的空間的地址

(2)  arr錶示第一行的地址,arr+2-----》錶示偏移到第三行,*(arr+2)錶示第三行第一個元素的地址

*(arr+2)+3---》錶示偏移到第三行第四個元素的地址---》*(*(arr+2)+3)---》錶示第三行第四個元素本身

(3)  s錶示指針數組中第一個元素的地址,s+2---》錶示偏移到指針數組中第三個元素的地址

*(s+2)---》錶示第三行第一個元素的地址,*(s+2)+3---》錶示第三行第四個元素的地址

*(*(s+2)+3)錶示第三行第四個元素的本身

(4)  arr+1要跳過16個字節,而s+1只跳過4個字節

動態的二維數組和棧上的二維數組的區別是,動態的二維數組在內存中不一定是連續的,它是通過指針串起來的,所以他只是在邏輯上是連續的。而棧上的二維數組不管是邏輯還是內存中都是連續的

版权声明:本文为[LoveHoneyYou]所创,转载请带上原文链接,感谢。 https://gsmany.com/2022/01/202201080300175698.html