繁体   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