數組

可變數組

變量數組

gcc規範明肯定義,數組長度可設置爲變量,可測試以下程序。linux

#include <stdio.h>
int main(int argc, char *argv[])
{
    int  n;
    n = atoi(argv[1]);
    char arr[n];
    memset(arr,'a',sizeof(arr)-1);
    arr[n-1] = '\0';
    printf("%s\n", arr);
    return (0);
}

執行指令:數組

./test 10

輸出結果:函數

aaaaaaaaa

0長數組

早期版本的linux內核中常常見到0長數組,例如:學習

struct data{
    int len;
    char buffer[0];
    }

buffer[0]和buffer[]同樣不佔用空間,且地址緊跟在結構後面,直接從buffer的地址開始訪問必定的長度就是直接訪問數組,若是使用指針,而char *buffer做爲指針,指針會佔用4個字節,地址不在結構以後。
數組的長度雖然可變,可是設置以後沒法更改。
申請長度時使用:測試

struct data * p_data = malloc(sizeof(struct data) + buffer_len)

buffer_len爲設定數組buffer的長度,此時設置data.len=buffer_len,此時的結構體長度可以使用sizeof(struct data)+data.len來計算,在釋放時只需使用free(p_data)便可釋放。
若是使用指針的話,申請須要兩次,釋放也須要兩次。指針

可變長數組(variable length array,簡稱 VLA)雖然可以靈活使用,而且在以前的linux內核中有個很多的應用,可是它嚴重下降了效率,這也就是爲何c語言至今沒有動態可變數組的實現的緣由之一,如今很多的動態擴展的數組表面上顯得靈活易用,實際上都是犧牲了效率,可是在linux內核這種追求極致的項目中,這是不被看好的。
新版本的linux內核5.0開始將會逐步減小對VLA的使用,編譯過程當中可以使用「-Wvla」編譯器標誌會發出警告,來提醒不要再使用VLA。code


數組初始化

關於數組的初始化經常使用的方法爲編譯器

int array[10] =  {0};

此時全部的內容將會被填充0,可能有些同窗會認爲使用此方法可將數組初始化爲其餘的值,例如:io

int array[10] = {1};

有的同窗可能以爲數組不會被1填充,其實否則,此時只有數組的第一個元素被填充爲1,其他的唄填充爲0。
那爲何第一種方法會被所有填充爲0呢?
緣由是,第一種寫反其實也只是將數組的第一個值初始化爲0,此時編譯器會默認將其餘的值以0填充,這就形成了一種所有被初始化爲0的假象。
那有沒有一種方法能初始化爲其餘的內容呢,答案是有的,編譯

  • 方法一:循環賦值
    這種方法太low,誰都會。
  • 方法二:定義時初始化
    例如:

    int array[10] = { [0 ... 9] = 1};

    固然這種方法也有缺陷,就是必須在定義的時候立馬賦值,可是能達到目的。


數組退化爲指針

直接上代碼

#include <stdio.h>
void test(int arr[]) {
    printf("test1 \n");
    printf("size = %d \n",sizeof(arr));
    printf("a[0] = %d\n", arr[0]);
    printf("a[9] = %d\n", arr[9]);
    printf("------\n\n");
}
int main() {
    int a[10] = {[0 ... 9] = 1};
    printf("main \n");
    printf("size = %d \n",sizeof(a));
    printf("a[0] = %d\n", a[0]);
    printf("a[9] = %d\n", a[9]);
    printf("------\n\n");
    test(a);
}

運行結果爲

main
size = 40
a[0] = 1
a[9] = 1
------

test1
size = 8
a[0] = 1
a[9] = 1
------

有些同窗可能以爲奇怪,爲何兩次的數組的內容相同,可是一樣是sizeof函數,輸出的內容卻不一樣呢?
int爲4字節(32位和64位,16位不考慮),數組長度10,顯示40,那8是怎麼來的呢?
答案是:數組在函數參數傳遞的時候退化爲指針了。
個人測試機器是64位,則第二次輸出長度的時候sizeof(int )就變成了8(8字節,1字節8位,88),其實退化爲指針後有一個操做是方便了,它失去了數組名的常亮特性,能夠被更改,那就是自加操做,arr++,經過自加來取數組的內容。位退化以前,數組名字做爲一個常亮是不容許自加操做的。那怎麼才能獲取到數組的長度呢,目前我沒有發現好的方法,可以使使用參數傳遞長度,有知道的同窗能夠評論告訴我,一塊兒學習。

相關文章
相關標籤/搜索