C語言變長數組data[0]【總結】

C語言變長數組data[0]【總結】

1、前言

  

  今天在看代碼中遇到一個結構中包含char data[0],第一次見到時感覺很奇怪,數組的長度怎么可以為零呢?于是上網搜索一下這樣的用法的目的,發現在linux內核中,結構體中經常用到data[0]。這樣設計的目的是讓數組長度是可變的,根據需要進行分配。方便操作,節省空間。

2、data[0]結構

經常遇到的結構形狀如下:

struct buffer
{int data_len;   //長度char data[0];  //起始地址
};

? 在這個結構中,data是一個數組名;但該數組沒有元素;該數組的真實地址緊隨結構體buffer之后,而這個地址就是結構體后面數據的地址(如果給這個結構體分配的內容大于這個結構體實際大小,后面多余的部分就是這個data的內容);這種聲明方法可以巧妙的實現C語言里的數組擴展。

  

  寫個程序對比char data[0],char *data, char data[],如下所示:

 

復制代碼
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #include <stdint.h>
 5 
 6 typedef struct
 7 {
 8     int data_len;
 9     char data[0];
10 }buff_st_1;
11 
12 typedef struct
13 {
14     int data_len;
15     char *data;
16 }buff_st_2;
17 
18 typedef struct 
19 {
20     int data_len;
21     char data[];
22 }buff_st_3;
23 
24 int main()
25 {
26     printf("sizeof(buff_st_1)=%u\n", sizeof(buff_st_1));
27     printf("sizeof(buff_st_2)=%u\n", sizeof(buff_st_2));
28     printf("sizeof(buff_st_3)=%u\n", sizeof(buff_st_3));
29 
30     buff_st_1 buff1;
31     buff_st_2 buff2;
32     buff_st_3 buff3;
33 
34     printf("buff1 address:%p,buff1.data_len address:%p,buff1.data address:%p\n",
35         &buff1, &(buff1.data_len), buff1.data);
36 
37     printf("buff2 address:%p,buff2.data_len address:%p,buff2.data address:%p\n",
38         &buff2, &(buff2.data_len), buff2.data);
39 
40     printf("buff3 address:%p,buff3.data_len address:%p,buff3.data address:%p\n",
41         &buff3, &(buff3.data_len), buff3.data);
42 
43     return 0;
44 }
復制代碼

從結果可以看出data[0]和data[]不占用空間,且地址緊跟在結構后面,而char *data作為指針,占用4個字節,地址不在結構之后。

3、實際當中的用法

???? 在實際程序中,數據的長度很多是未知的,這樣通過變長的數組可以方便的節省空間。對指針操作,方便數據類型的轉換。測試程序如下:

復制代碼
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #include <stdint.h>
 5 
 6 typedef struct
 7 {
 8     int data_len;
 9     char data[0];
10 }buff_st_1;
11 
12 typedef struct
13 {
14     int data_len;
15     char *data;
16 }buff_st_2;
17 
18 typedef struct 
19 {
20     int data_len;
21     char data[];
22 }buff_st_3;
23 
24 typedef struct 
25 {
26     uint32_t id;
27     uint32_t age;
28 }student_st;
29 
30 
31 void print_stu(const student_st *stu)
32 {
33     printf("id:%u,age:%u\n", stu->id, stu->age);
34 }
35 
36 int main()
37 {
38     student_st *stu = (student_st *)malloc(sizeof(student_st));
39     stu->id = 100;
40     stu->age = 23;
41 
42     student_st *tmp = NULL;
43 
44     buff_st_1 *buff1 = (buff_st_1 *)malloc(sizeof(buff_st_1) + sizeof(student_st));
45     buff1->data_len = sizeof(student_st);
46     memcpy(buff1->data, stu, buff1->data_len);
47     printf("buff1 address:%p,buff1->data_len address:%p,buff1->data address:%p\n",
48         buff1, &(buff1->data_len), buff1->data);
49 
50     tmp = (student_st*)buff1->data;
51     print_stu(tmp);
52 
53     buff_st_2 *buff2 = (buff_st_2 *)malloc(sizeof(buff_st_2));
54     buff2->data_len = sizeof(student_st);
55     buff2->data = (char *)malloc(buff2->data_len);
56     memcpy(buff2->data, stu, buff2->data_len);
57     printf("buff2 address:%p,buff2->data_len address:%p,buff2->data address:%p\n",
58         buff2, &(buff2->data_len), buff2->data);
59 
60     tmp = (student_st *)buff2->data;
61     print_stu(tmp);
62 
63     buff_st_3 *buff3 = (buff_st_3 *)malloc(sizeof(buff_st_3) + sizeof(student_st));
64     buff3->data_len = sizeof(student_st);
65     memcpy(buff3->data, stu, buff3->data_len);
66     printf("buff3 address:%p,buff3->data_len address:%p,buff3->data address:%p\n",
67         buff3, &(buff3->data_len), buff3->data);
68 
69     tmp = (student_st*)buff1->data;
70     print_stu(tmp);
71 
72     free(buff1);
73 
74     free(buff2->data);
75     free(buff2);
76 
77     free(buff3);
78     free(stu);
79     return 0;
80 }
復制代碼

程序執行結果如下:
? 采用char *data,需要進行二次分配,操作比較麻煩,很容易造成內存泄漏。而直接采用變長的數組,只需要分配一次,然后進行取值即可以。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/253214.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/253214.shtml
英文地址,請注明出處:http://en.pswp.cn/news/253214.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Excel 轉為 MySQL 語句

一、方法 一、假設你的表格有A、B、C三列數據&#xff0c;希望導入到你的數據庫中表格table&#xff0c;對應的字段分別是col1、col2、col3 二、在你的表格中增加一列&#xff0c;利用excel的公式自動生成sql語句&#xff0c;具體方法如下&#xff1a; 1、增加一列&#xff08;…

CentOS7下安裝zookeeper3.4.9

獲取zookeeper官方安裝包 1 wget https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/zookeeper-3.4.9/zookeeper-3.4.9.tar.gz 解壓該文件包 1 tar zxf zookeeper-3.4.9.tar.gz 進入conf文件夾并創建新配置文件 1 cd zookeeper-3.4.9/conf 2 vi zoo.cfg 在config文件中加…

union 和 struct 的區別與聯系

union &#xff08; 共用體&#xff09;&#xff1a;構造數據類型,也叫聯合體 用途&#xff1a;使幾個不同類型的變量共占一段內存(相互覆蓋) struct ( 結構體 )&#xff1a;是一種構造類型 用途&#xff1a; 把不同的數據組合成一個整體——自定義數據類型 主要區別&#x…

Android系統中標準Intent的使用

Android系統用于Activity的標準Intent 1.根據聯系人ID顯示聯系人信息 Intent intentnew Intent(); intent.setAction(Intent.ACTION_VIEW);//顯示聯系人信息 intent.setData(Uri.parse("content://contaccts/people/492")); startActivity(intent); 2.根據聯系人ID顯…

開關電源簡介

1. 基本分類 DC-DC BULK電源 DC-DC BOOST電源 DC-DC BULK/BOOST電源 DC-DC BOOST/BYPASS電源 2. 典型拓撲結構 BULK電路拓撲 降壓型電源 串聯關系在開關管S導通時&#xff0c;二極管VD負極電壓高于正極反偏截止&#xff0c;此時電流經過電感L向電容和負載供電&#x…

Office 2016中Excel的部分快捷方式

【Ctrl下箭頭】 拉到最后一行 【Alt 】一秒求和 【CtrlEnter】 一秒輸入相同數據 【Ctrld】 一秒豎向填充不連續區域 【Ctrlr】 一秒向右填充數據 【Ctrle】 批量提取字符 【Ctrl1】 調出 設置單元格格式窗口 【Ctrlz】 撤銷上一步操作 【Ctrly】 恢復上一步 【F4】 重復上一步…

基于Spring開發的DUBBO服務接口測試

基于Spring開發的DUBBO服務接口測試 知識共享主要內容&#xff1a; 1、 Dubbo相關概念和架構&#xff0c;以及dubbo服務程序開發步驟。 2、 基于Spring開發框架的dubbo服務接口測試相關配置。 3、 spring testjunit和spring testTestNG兩種測試框架腳本編寫方法。 一、 …

ioctl之FIONREAD

在學習ioctl 時常常跟 read, write 混淆。其實 ioctl 是用來設置硬件控制寄存器&#xff0c;或者讀取硬件狀態寄存器的數值之類的。 而read,write 是把數據丟入緩沖區&#xff0c;硬件的驅動從緩沖區讀取數據一個個發送或者把接收的數據送入緩沖區。 ioctl(keyFd, FIONREAD, &a…

電感基礎與選型介紹

電感是一種常見的被動元件&#xff0c;常用在LC振蕩電路、中低頻的濾波電路&#xff0c;DCDC能量轉換電路中&#xff0c;其應用頻率一般不超過50MHz。 1.電感的主要作用 通直流&#xff0c;阻交流阻交流變化&#xff0c;保持電流穩定----楞次定律濾波 2.電感的主要分類 3.電…

[題解]Codeforces Round #519 - B. Lost Array

【題目】 B. Lost Array 【描述】 Bajtek有一個數組x[0],x[1],...,x[k-1]但被搞丟了&#xff0c;但他知道另一個n1長的數組a&#xff0c;有a[0]0&#xff0c;對i1,2,...,n。由此可以找到數組x[0],x[1],...,x[k-1]的一些可能情況&#xff0c;即滿足這個關系的數組x[0],x[1],...,…

Python正則替換字符串函數re.sub用法示例(1)

本文實例講述了Python正則替換字符串函數re.sub用法。分享給大家供大家參考&#xff0c;具體如下&#xff1a; python re.sub屬于python正則的標準庫,主要是的功能是用正則匹配要替換的字符串然后把它替換成自己想要的字符串的方法re.sub 函數進行以正則表達式為基礎的替換工作…

LeetCode 24 Swap Nodes in Pairs (交換相鄰節點)

題目鏈接&#xff1a; https://leetcode.com/problems/swap-nodes-in-pairs/?tabDescriptionProblem: 交換相鄰的兩個節點如上圖所示&#xff0c;遞歸進行交換。從最尾端開始&#xff0c;當最尾端只有一個節點時&#xff0c;停止交換否則執行 swap(head.next) 參考代碼&#x…

Netra基于Rdk平臺的軟件框架設計

Netra&#xff08;DM8168&#xff09;處理器是個多核處理器&#xff0c;每個核之間相互獨立卻又相互關聯&#xff0c;如何高效簡潔地利用每個核完成一套系統功能是非常關鍵的&#xff0c;RDK這套軟件平臺就是針對這種多核平臺設計的一套多通道視頻應用方案&#xff0c;主要用于…

電感嘯叫原因與應對措施

大部分硬件工程師應該都遇到過,PCBA上電后出現“滋滋滋”的叫聲,其聲響或大或小,或時有時無,或深沉或刺耳,或變化無常者皆有。該現象我們稱為“嘯叫”,一般分為電感嘯叫和電容嘯叫。 其中電感嘯叫最為常見,尤其在DCDC電路中,大部分是因為 器件參數選擇不合理 導致的。…

ASP.NET Web API 記錄請求響應數據到日志的一個方法

原文:ASP.NET Web API 記錄請求響應數據到日志的一個方法原文&#xff1a;http://blog.bossma.cn/dotnet/asp-net-web-api-log-request-response/ ASP.NET Web API 記錄請求響應數據到日志的一個方法 REST風格的服務架構已經成為越來越多人的選擇&#xff0c;之前我用過WCF來實…

Nginx + php

Nginx php 目前有兩種方式1.nginx apache nginx 負責靜態內容、反向代理和保持連接&#xff0c;apache則負責處理動態內容。 2.nginx fastcgi php-fpm一、nginx apache 采用Nginx前端Apache后端的服務器架構&#xff0c;這樣可以很好地結合了Nginx高并發和靜態頁面高效率以…

Android Fragment完全解析,關于碎片你所需知道的一切

我們都知道&#xff0c;Android上的界面展示都是通過Activity實現的&#xff0c;Activity實在是太常用了&#xff0c;我相信大家都已經非常熟悉了&#xff0c;這里就不再贅述。 但是Activity也有它的局限性&#xff0c;同樣的界面在手機上顯示可能很好看&#xff0c;在平板上就…

圖像--攝像頭組成與基本參數

基本組成 Sensor: 圖象傳感器 FPC: 電路板 IR:紅外濾波片 Holder:基座 Lens:鏡頭 其他 核心部件&#xff1a;1- SENSOR 2- LENS Sensor參數 類別 指標 參考 備注 Sensor 廠家 sony 三星 OV 格科微由原廠提供完整規格書和型號 低像素需要注意 分辨率 0.3MP (VGA)模組…

1.I2C協議

1.I2C協議2條雙向串行線&#xff0c;一條數據線SDA&#xff0c;一條時鐘線SCL。SDA傳輸數據是大端傳輸&#xff0c;每次傳輸8bit&#xff0c;即一字節。支持多主控(multimastering)&#xff0c;任何時間點只能有一個主控。總線上每個設備都有自己的一個addr&#xff0c;共7個bi…