国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

C語(yǔ)言可變數(shù)組 嵌套的可變數(shù)組,翻過了山跨過了河 又掉進(jìn)了坑

這篇具有很好參考價(jià)值的文章主要介紹了C語(yǔ)言可變數(shù)組 嵌套的可變數(shù)組,翻過了山跨過了河 又掉進(jìn)了坑。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

可變數(shù)組

?專欄內(nèi)容
postgresql內(nèi)核源碼分析
手寫數(shù)據(jù)庫(kù)toadb
并發(fā)編程
個(gè)人主頁(yè):我的主頁(yè)
座右銘:天行健,君子以自強(qiáng)不息;地勢(shì)坤,君子以厚德載物.

C語(yǔ)言可變數(shù)組 嵌套的可變數(shù)組,翻過了山跨過了河 又掉進(jìn)了坑,C語(yǔ)言特性,c語(yǔ)言,開發(fā)語(yǔ)言,linux,后端

概述

數(shù)組中元素是順序存放,這一特性讓我們存儲(chǔ)和訪問數(shù)據(jù)都很簡(jiǎn)單,
但也因?yàn)檫@一特性,我們?cè)趯懘a時(shí),往往不能確定數(shù)組元組的個(gè)數(shù),只能按最大的數(shù)量進(jìn)行預(yù)分配,
這不僅造成了空間浪費(fèi),而且使用起來不友好,明明我們要運(yùn)行一個(gè)小數(shù)據(jù)集,但卻要很多內(nèi)存空間。

這就產(chǎn)生了可變數(shù)組,它的元素?cái)?shù)量不需要在代碼中確定,而是在運(yùn)行時(shí)確定。

實(shí)現(xiàn)方式

可變數(shù)組在我們的程序中經(jīng)常遇到,但是它有那些實(shí)現(xiàn)方式呢?
根據(jù)數(shù)組存儲(chǔ)內(nèi)存區(qū)域的不同,可以分為

  • 棧內(nèi)存實(shí)現(xiàn)方式
  • 堆內(nèi)存實(shí)現(xiàn)方式
    下面我們就來看看它們是如何實(shí)現(xiàn),有什么不同

棧內(nèi)存實(shí)現(xiàn)

這里C99中新增的VLA(variable-length array) 特性,可以讓我們?cè)谟玫臅r(shí)候定義數(shù)組,數(shù)組的長(zhǎng)度不再是靜態(tài)值,可以是變量中的值。
也就是說,數(shù)組的長(zhǎng)度在程序編譯階段是不確定的,直到運(yùn)行時(shí)再能確定,這就避夠我們定義一個(gè)最大的數(shù)組,產(chǎn)生很多空間浪費(fèi)。

  • 舉例
void test(int n)
{
    /* check */
    if(n <= 0)
    {
        return;
    }

    // int arr[n] = {0};
    int arr[n];
    /* todo  */
    for(int i=0; i < n; i++)
    {
        arr[i] = i;
    }
    return;
}

數(shù)組arr的長(zhǎng)度是變量n來確定

  • 注意事項(xiàng)
  1. 這個(gè)特性是C99引入,并不是所有的編譯器都能完全支持,我使用的 gcc 版本是支持的。
[senllang@hatch toadbtest]$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/8/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-redhat-linux
Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,fortran,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl --disable-libmpx --enable-offload-targets=nvptx-none --without-cuda-driver --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux
Thread model: posix
gcc version 8.5.0 20210514 (Red Hat 8.5.0-19) (GCC)
  1. 使用VLA定義的數(shù)組,不能在定義時(shí)初始化,否則會(huì)產(chǎn)生以下錯(cuò)誤,因?yàn)樗荒苁褂媚J(rèn)的初始化器,必須由用戶自己來初始化;
[senllang@hatch toadbtest]$ gcc test.c
test.c: In function ‘test’:
test.c:9:5: error: variable-sized object may not be initialized
     int arr[n] = {0};
     ^~~
test.c:9:19: warning: excess elements in array initializer
     int arr[n] = {0};

堆內(nèi)存實(shí)現(xiàn)

在用的時(shí)候,通過malloc動(dòng)態(tài)申請(qǐng)數(shù)組空間,空間大小為 數(shù)組元素類型的n倍,n是我們需要的數(shù)組大小,它可以是輸入,也可以是程序運(yùn)行過程中的可變值。

這種方式是我們普遍使用的,也是所有編譯器都支持的。

  • 舉例
void test(int n)
{
    int *arr = NULL;

    /* check */
    if(n <= 0)
    {
        return;
    }

    arr = (int *)malloc(sizeof(int)*n);
    if(NULL == arr)
    {
        return ;
    }

    /* todo  */
    for(int i=0; i < n; i++)
    {
        arr[i] = i;
    }
    return;
}

訪問方式

數(shù)組訪問一般有指針方式和下標(biāo)方式,這與普通數(shù)組沒有什么區(qū)別,為什么要談數(shù)組的訪問方式呢? 因?yàn)檫@里會(huì)隱藏著驚天大坑,我們接著往下看。

C語(yǔ)言里一般,數(shù)組可以轉(zhuǎn)成指針,當(dāng)然指針也可以轉(zhuǎn)成數(shù)組來用。

數(shù)組下標(biāo)訪問

這就很簡(jiǎn)單了,數(shù)組中的元素都是順序排列,那么按它們的位置序號(hào)訪問就可以。

對(duì)于VLA方式定義,還是動(dòng)態(tài)申請(qǐng)方式分配的空間,它們的元素存儲(chǔ)的內(nèi)存空間都是連續(xù)的,所以兩種方式下都可以用下標(biāo)的方式來訪問。

  • 對(duì)于數(shù)組,那就再正常不過了,遞增下標(biāo)就可以獲取到各元素的值;
  • 而對(duì)于動(dòng)態(tài)申請(qǐng)的數(shù)組,本身就是指向內(nèi)存空間的首地址,也可以理解為指向數(shù)組的指針,即常說的數(shù)組指針,用下標(biāo)的方式就可以直接獲取到對(duì)應(yīng)的元素值。
/* 如上面舉例,指針類型定義的數(shù)組,也可以下標(biāo)進(jìn)行訪問 */
int *arr = NULL;
arr[i] = i;

指針訪問

指針形式訪問,每次指針的移動(dòng)步長(zhǎng),都是指針基礎(chǔ)類型的字節(jié)數(shù);
此時(shí)取值時(shí),就要以指針的方式來取值;

對(duì)于VLA方式定義,還是動(dòng)態(tài)申請(qǐng)方式分配的空間,它們的元素存儲(chǔ)的內(nèi)存空間都是連續(xù)的,所以兩種方式下都可以用指針的方式來訪問。

  • 對(duì)于數(shù)組,數(shù)組名就是首個(gè)元素的地址,遍歷時(shí)每次遞增+1,就會(huì)移動(dòng)到下一個(gè)元素的地址;
  • 而對(duì)于動(dòng)態(tài)申請(qǐng)的數(shù)組,本身就是指向內(nèi)存空間的首地址,也是0號(hào)元素的首地址;
int testarr[n];
int *arr = testarr;

for(int i = 0; i < n; i++,arr++)
{
    *arr = i;
}

此處專門定義一個(gè)數(shù)組,然后將數(shù)組首地址賦給指針,用指針來訪問數(shù)組元素

可變數(shù)組的嵌套使用

如果一個(gè)結(jié)構(gòu)體里含有可變數(shù)組,同時(shí)結(jié)構(gòu)體又存在嵌套,看起來都有點(diǎn)復(fù)雜,那它如何分配空間和訪問呢?

定義

假如我們定義如下結(jié)構(gòu)體,最終我們使用的是 stGroupData 這個(gè)結(jié)構(gòu)體;

typedef struct Postion
{
    int x;
    int y;
}stPosition, *pstPostion;

typedef struct MemberData
{
    int posCnt;
    stPosition posArr[];
}stMemberData, *pstMemberData;

typedef struct GroupData
{
    int group_id;
    int memberCnt;
    stMemberData memberData[];
}stGroupData, *pstGroupData;

大家是否好奇,上面結(jié)構(gòu)的大小時(shí)多少呢?這個(gè)留給大家一個(gè)作業(yè),知道答案的同學(xué)可以在評(píng)論區(qū)給出來。

分配空間

因?yàn)榇嬖谇短?,所以就不能用VLA這個(gè)特性了,只能用動(dòng)態(tài)分配了。
動(dòng)態(tài)分配時(shí),需要對(duì)外層結(jié)構(gòu)體和內(nèi)層結(jié)構(gòu)體的元素分別計(jì)算,這里很容易遺漏;

假設(shè)我們有一組數(shù)據(jù),需要2個(gè)memberdata:

memberdata 0: 有3個(gè)postion
memberdata 1: 有1個(gè)postion

坑一:占用空間

空間需要分配多少呢?

  • 可能初看好像是sizeof(stGroupData) 就可以了;
  • 再看,其實(shí)需要 sizeof(stGroupData) + 2*sizeof(stMemberData) 大??;

這就掉坑里了。下面是正確的大小計(jì)算;

計(jì)算空間大小

int size = 0;
pstGroupData pgData = NULL;

/* 計(jì)算一個(gè)要分配的空間大小,假設(shè)2個(gè)memberdata:
 * memberdata 0: 有3個(gè)postion
 * memberdata 1: 有1個(gè)postion 
 */
size = sizeof(stGroupData) + 2*sizeof(stMemberData) + 4 * sizeof(stPosition);
pgData = (pstGroupData)malloc(size);

這里計(jì)算size時(shí),先計(jì)算結(jié)構(gòu)體頭部的size,因?yàn)閿?shù)組部分沒有定義長(zhǎng)度,sizeof 出的來的值是不包含的,所以需要單獨(dú)計(jì)算;
外層stGroupData中包含兩個(gè)元素, 內(nèi)層 stMemberData中分別為 3和1,也就是4個(gè)元素空間 ,再加上外層的結(jié)構(gòu)體大小,就是整個(gè)所占的內(nèi)存空間。
它們的內(nèi)存空間分布情況,假設(shè)首地址從0開始

C語(yǔ)言可變數(shù)組 嵌套的可變數(shù)組,翻過了山跨過了河 又掉進(jìn)了坑,C語(yǔ)言特性,c語(yǔ)言,開發(fā)語(yǔ)言,linux,后端

訪問數(shù)組

那么按上面的例子,定義了一個(gè)結(jié)構(gòu)體,如何訪問各個(gè)數(shù)組元素呢?
可能有小伙伴立刻就想到了下標(biāo)的方式 ,那么我們來看一下

坑二:下標(biāo)訪問

此時(shí)我們用下標(biāo)方式引用會(huì)是正確的嗎?

pgData->memberData[0] 
pgData->memberData[1] 

memberData[0] 與 memberData[1]的地址相差,應(yīng)該是一個(gè)元素的sizeof(stMemberData) = 4,也就是一個(gè)int posCnt空間大??;
從內(nèi)存分布圖來看,就會(huì)變成這樣

C語(yǔ)言可變數(shù)組 嵌套的可變數(shù)組,翻過了山跨過了河 又掉進(jìn)了坑,C語(yǔ)言特性,c語(yǔ)言,開發(fā)語(yǔ)言,linux,后端

嵌套可變數(shù)組的訪問

此時(shí)下標(biāo)訪問是不對(duì)的,不能采用默認(rèn)的類型大小進(jìn)行移動(dòng);
只能用指針方式來訪問,同時(shí)需要自己計(jì)算下一個(gè)元素的偏移大小

pstMemberData pmData = NULL;

/* memberData[0] */
pmData = pgData->memberData;

/* memberData[1] */
pmData = (pstMemberData)((char*)(pgData->memberData) + sizeof(stMemberData) + 3 * sizeof(stPosition));

結(jié)尾

非常感謝大家的支持,在瀏覽的同時(shí)別忘了留下您寶貴的評(píng)論,如果覺得值得鼓勵(lì),請(qǐng)點(diǎn)贊,收藏,我會(huì)更加努力!

作者郵箱:study@senllang.onaliyun.com
如有錯(cuò)誤或者疏漏歡迎指出,互相學(xué)習(xí)。

注:未經(jīng)同意,不得轉(zhuǎn)載!文章來源地址http://www.zghlxwxcb.cn/news/detail-657120.html

到了這里,關(guān)于C語(yǔ)言可變數(shù)組 嵌套的可變數(shù)組,翻過了山跨過了河 又掉進(jìn)了坑的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 11-數(shù)組-二維區(qū)域和檢索 - 矩陣不可變

    11-數(shù)組-二維區(qū)域和檢索 - 矩陣不可變

    這是數(shù)組的第11篇算法,力扣鏈接。 給定一個(gè)二維矩陣? matrix ,以下類型的多個(gè)請(qǐng)求: 計(jì)算其子矩形范圍內(nèi)元素的總和,該子矩陣的? 左上角 ?為? (row1,?col1) ?, 右下角 ?為? (row2,?col2) ?。 實(shí)現(xiàn)? NumMatrix ?類: NumMatrix(int[][] matrix) ?給定整數(shù)矩陣? matrix ?進(jìn)行初始化 int

    2024年01月24日
    瀏覽(21)
  • leetcode303. 區(qū)域和檢索 - 數(shù)組不可變(java)

    leetcode303. 區(qū)域和檢索 - 數(shù)組不可變(java)

    難度 - 簡(jiǎn)單 原題鏈接 - 區(qū)域和檢索 - 數(shù)組不可變 給定一個(gè)整數(shù)數(shù)組 nums,處理以下類型的多個(gè)查詢: 計(jì)算索引 left 和 right (包含 left 和 right)之間的 nums 元素的 和 ,其中 left = right 實(shí)現(xiàn) NumArray 類: NumArray(int[] nums) 使用數(shù)組 nums 初始化對(duì)象 int sumRange(int i, int j) 返回?cái)?shù)組 num

    2024年02月12日
    瀏覽(23)
  • Hive解析嵌套JSON數(shù)組

    同時(shí)發(fā)生的埋點(diǎn)數(shù)據(jù)往往會(huì)在一個(gè)json字符串里發(fā)送,形式是[json,json,json]的埋點(diǎn)數(shù)組,需要把這些數(shù)據(jù)拉平 把最外層的\\\"[“和”]\\\"去除 把\\\"},{“轉(zhuǎn)換為”}|||{\\\" ,使用split函數(shù)根據(jù)\\\"|||\\\"把string轉(zhuǎn)為array,LATERAL view explode()把a(bǔ)rray轉(zhuǎn)為列 第二步的時(shí)候發(fā)現(xiàn),內(nèi)部的json數(shù)組也有\(zhòng)\\"},

    2024年02月12日
    瀏覽(17)
  • C++中使用嵌套循環(huán)遍歷多維數(shù)組

    一維數(shù)組:數(shù)組元素可以看做是一行數(shù)據(jù)。 二維數(shù)組:更像是一個(gè)表格,既有行數(shù)據(jù)又有列數(shù)據(jù)。 C++沒有提供二維數(shù)組類型,但用戶可以創(chuàng)建每個(gè)元素本身都是數(shù)組的數(shù)組。例如,假設(shè)要存儲(chǔ) 5 個(gè)城市在 4 年間的最高氣溫,可以這樣聲明數(shù)組: 該聲明意味著 maxtemps 是一個(gè)包

    2024年02月07日
    瀏覽(34)
  • Mongodb 對(duì)嵌套文檔數(shù)組進(jìn)行查詢操作

    非嵌套文檔的數(shù)組,數(shù)組由數(shù)字、字符串等元素組成。 以下方法對(duì)數(shù)組字段進(jìn)行查詢操作的示例,包括對(duì)數(shù)組匹配查詢,元素的增、刪、改操作,空數(shù)組、非空數(shù)組查詢等。 連接到 mongodb 數(shù)據(jù)庫(kù), 創(chuàng)建集合 user, 批量插入如下測(cè)試數(shù)據(jù) : 在指定數(shù)組上的使用相等條件,請(qǐng)

    2024年02月17日
    瀏覽(15)
  • MongoDB原生語(yǔ)句更新嵌套數(shù)組的值

    MongoDB原生語(yǔ)句更新嵌套數(shù)組的值

    首先執(zhí)行MongoDB原生語(yǔ)句腳本在user集合中產(chǎn)生一些樣本數(shù)據(jù),如下所示: 如果想將 “ 呂子喬 ” 修改為 “ 曾小賢 ” ,則可以執(zhí)行下述腳本進(jìn)行數(shù)據(jù)更新: 這時(shí)再次查看user集合,可以看到數(shù)據(jù)已經(jīng)更新: 此處使用了$符號(hào),$符號(hào)表示的是一個(gè)占位符,代表被匹配的數(shù)組中的

    2024年02月15日
    瀏覽(17)
  • 二維數(shù)組多次排序 或 嵌套list多次排序

    可以排序int[ ][ ]的順序,也可以排序ListListInteger 順序 為便于理解,以力扣原題為例:1333.餐廳過濾器 原題中給了一個(gè)雙重?cái)?shù)組,并要求返回一個(gè)ListInteger。 方法1 : 會(huì)用流的,通常用于會(huì)反應(yīng)把雙重?cái)?shù)組轉(zhuǎn)成ListListInteger去處理這個(gè)雙重?cái)?shù)組,于是解題思路如下: 可是該方式

    2024年02月07日
    瀏覽(19)
  • c語(yǔ)言可變形參

    一般的函數(shù)的參數(shù)列表都是固定的,但是偶爾也會(huì)想要根據(jù)情況使用動(dòng)態(tài)的列表。 1.可變形參的形式 返回類型 函數(shù)名(第一個(gè)參數(shù), ...); 可變形參的函數(shù)如上,需要提供第一個(gè)參數(shù),后面用... 2.函數(shù)用到的特殊東西 va_list是一種特殊的指針,在使用可變形參之前,需要定義它。

    2024年02月15日
    瀏覽(22)
  • vue +element UI form表單校驗(yàn)數(shù)組嵌套,數(shù)組對(duì)象必填校驗(yàn)

    vue +element UI form表單校驗(yàn)數(shù)組嵌套,數(shù)組對(duì)象必填校驗(yàn)

    使用element表單時(shí)會(huì)出現(xiàn)數(shù)組對(duì)象類型的數(shù)據(jù)結(jié)構(gòu)并且需要必填校驗(yàn) 這時(shí)數(shù)組對(duì)象的檢驗(yàn)方法就為paramJsonListRules 注意的是為了實(shí)現(xiàn)校驗(yàn),在需要校驗(yàn)的el-form-item內(nèi)通過自己的:rules加入對(duì)象的校驗(yàn)方法,例如圖中想給參數(shù)值加校驗(yàn)則直接在相關(guān)el-form-item內(nèi)加入 :rules=\\\"paramJsonLis

    2024年02月11日
    瀏覽(29)
  • vue+elementui表單數(shù)組對(duì)象深層嵌套之自定義驗(yàn)證規(guī)則

    需求場(chǎng)景:在Vue+Elementui項(xiàng)目中,需要在表單的循環(huán)數(shù)組中,對(duì)某一深層嵌套的對(duì)象屬性制定自定義校驗(yàn)規(guī)則。

    2024年02月05日
    瀏覽(37)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包