簡體   English   中英

ANSI C-初始化數組

[英]ANSI C - initializing an array

我一直在做的是:

int arr[] = {2, 3, 4};

並且一直有效。

我聽說過使用指針初始化新數組的更好方法:

int *arr = {2, 3, 4};

但是,它在任何IDE中均不起作用,它會引發一些錯誤,例如int differs in levels of indirection from int ,或者too many initializers 我應該怎么做?

int arr[] = {2, 3, 4};

很好,而且完全正確。 無需更改。

在gcc上,該初始化似乎對我有用,但不正確。

int *arr = {2, 3, 4}; //weird behaviour, stores first value `2` as read-only

int arr[] = {2, 3, 4}; //array decl

前者不是初始化數組的正確方法。

對於char * ,這更有意義

char* arr = "abcde"; //Pointer to a read-only char array in memory

char[] arr = "abcde"; //Normal char array

區別:

前者被寫入到程序集的Rodata (常量,只讀數據)部分,而后者則位於讀/寫Data-Segment中 嘗試更改前者可能會導致segmentation-fault


值的存儲位置不同。

char* arr = "abcde";
arr[1] = 'f'; //(undefined behavior)

char[] arr2 = "abcde";
arr2[1] = 'f'; //no issue

如果要“初始化數組”,則必須初始化一個數組 ,而不是一個指針。

無論如何,在C99中可以使用復合文字,並且可以將指針初始化為

int *arr = (int []) {2, 3, 4};

這與您嘗試執行的操作很接近。 盡管術語“ ANSI C”通常用於指代C89 / 90,但該功能不可用。

這種方法沒有“更好”的選擇。 它只是給您一個指針而不是一個數組,因此這實際上是您需要什么的問題。

為什么第二個版本會比第一個版本好?

至少第一個版本是顯式的:您使用給定的元素定義一個int數組。 讓編譯器確定如何最佳地執行此操作。

從您的評論轉到Evan Li(“字符串也是一種數組,並且使用指針對其進行了初始化。因此,數組也應以這種方式進行初始化。”)。 如果講師確實告訴過您,我會認真考慮尋找新的講師,因為他對事情感到困惑。

字符串文字是數組表達式。 文字“ Hello”是char的6個元素的數組(在C ++中為const char )。 字符串文字的存儲方式是在程序的生命周期內分配它們的內存。 該內存可能是只讀的,也可能不是只讀的,具體取決於平台。 嘗試修改字符串文字內容的行為是未定義的 ,這意味着您可能會遇到段錯誤,或者可能會修改字符串,或者發生其他情況。

當數組表達式出現在上下文中而不是作為sizeof或一元&運算符的操作數時,或者在聲明中使用字符串常量來初始化另一個數組時,表達式的類型將被轉換(“ decays”) “ T N個元素數組”到“指向T指針”,表達式的值是數組的第一個元素的地址。

這就是為什么你可以寫像

char *foo = "This is a test";

字符串文字"This is a test"是類型為“ 15個元素的char數組"This is a test"的數組表達式; 因為它不是sizeof&運算符的操作數,並且不用於初始化另一個char數組,所以表達式的類型變為“ char指針”,並且第一個字符的地址分配給foo 通過對比,

char foo[] = "This is a test";

foo聲明為char 數組 從初始化程序字符串的大小(15個字符)計算出大小,並將字符串文字的內容復制到foo

字符串是數組表達式; 大括號括起來的值列表不是

int *foo = {1, 2, 3};

不會創建一個3元素的int數組,並將第一個元素的地址分配給foo 相反,如果我正在閱讀權限,則應該違反約束:

6.7.9初始化

約束條件

2初始化程序不得嘗試為未包含在正在初始化的實體內的對象提供值。

從C99開始,您可以使用所謂的復合文字 ,如下所示:

int *foo = (int []) {1, 2, 3};

強制轉換表達式(int [])是必需的。 這確實創建了一個新的3元素int數組,並將第一個元素的地址分配給foo 與字符串文字不同,此類復合文字僅在封閉塊1的持續時間內存在; IOW,如果您做了類似的事情

int *foo = NULL;
if (condition())
{
  foo = (int []){1, 2, 3};
  // do stuff
}
// do more stuff

foo指向的匿名數組對象僅存在於if塊中; 一旦if塊退出,該數組將不再存在,並且foo的值不再有效。


1.如果復合文字在文件范圍內(在任何函數之外)定義,則它具有static持續時間,並且在程序的生存期內存在。

int arr [] = {2,3,4}; 還可以

如果要使用指針,則必須使用例如malloc分配內存。 像這樣:

  int *arr = malloc(sizeof(int)*4);

  arr[0]=1;
  arr[1]=2;
  arr[2]=3;
  arr[3]=4;

  //display
  printf("%d %d %d %d\n",arr[0],arr[1],arr[2],arr[3]);

  free(arr);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM