【问题标题】:Simple C array declaration / assignment question简单的 C 数组声明/赋值问题
【发布时间】:2010-12-07 14:50:49
【问题描述】:

在更高级的语言中,我可以在 C 中使用类似于此示例的内容,这很好。但是,当我编译这个 C 示例时,它抱怨得很厉害。如何将新数组分配给我声明的数组?

int values[3];

if(1)
   values = {1,2,3};

printf("%i", values[0]);

谢谢。

【问题讨论】:

标签: c arrays declaration variable-assignment


【解决方案1】:

声明数组时,只能对数组进行多次赋值:

int values[3] = {1,2,3};

声明后,您必须单独分配每个值,即

if (1) 
{
  values[0] = 1;
  values[1] = 2;
  values[2] = 3;
}

或者您可以使用循环,具体取决于您要使用的值。

if (1)
{
  for (i = 0 ; i < 3 ; i++)
  { 
    values[i] = i+1;
  }
}

【讨论】:

  • 这适用于 3 个值,但是如果我有一个包含 50 个值的数组呢?
  • 然后你会使用一个循环,或者你会memmove/memcpy就像@hacker在另一个答案中建议的那样。
  • memcpy 似乎最整洁。感谢您的帮助。
【解决方案2】:

在 C99 中,使用 compound literals,您可以:

memcpy(values, (int[3]){1, 2, 3}, sizeof(int[3]));

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

【讨论】:

  • +1;请记住,在后一种情况下,数组将具有自动存储持续时间,即从函数中返回它会让你被吃掉
  • Christoph,这是否意味着 memmove 从这样的数组中首先将其初始化到自动存储中,然后将其复制过来?
  • @hacker:原则上,是的,实际上,编译器会将其优化掉(对于 gcc,-O1 就足够了)
  • 另一方面,你确定它真的是自动存储吗?这不是类似于字符串文字吗?还是使用 const 关键字使其行为方式与字符串文字一样?
  • @hacker: 是的,const 复合文字可以像字符串一样共享(这是一个实现细节,与语言语义无关);非常量字面量保证在封闭块的每个条目上都是不同的
【解决方案3】:
 //compile time initialization
 int values[3] = {1,2,3};

//run time assignment
 value[0] = 1;
 value[1] = 2;
 value[2] = 3;

【讨论】:

    【解决方案4】:

    你可以用数据声明静态数组来初始化:

    static int initvalues[3] = {1,2,3};
    …
    if(1)
        memmove(values,initvalues,sizeof(values));
    

    【讨论】:

    • 我可以不做 memmove(values,{1,2,3},sizeof(values)); ?
    • 我认为你可以:memmove(values, (int[3]){1,2,3}, sizeof(int[3]));请参阅下面的答案。
    • 这里不需要使用memmove 而不是memcpy - 数组绝对不会重叠。
    • 你为什么认为我使用 memmove “over memcpy”?我刚刚使用了memmove。 ;-)
    • @Michael:@caf 的意思是在给定的场景中不需要移动内存,因为源和目标不重叠。这样,memcpy 可能会稍微快一些。看到这个stackoverflow.com/questions/1201319/…
    【解决方案5】:
    #include<stdio.h>
    #include<stdlib.h>
    #include<stdarg.h>
    
    int *setarray(int *ar,char *str)
    {
        int offset,n,i=0;
        while (sscanf(str, " %d%n", &n, &offset)==1)
        {
            ar[i]=n;
            str+=offset;
            i+=1;
        }
        return ar;
    }
    
    int *setarray2(int *ar,int num,...)
    {
       va_list valist;
       int i;
       va_start(valist, num);
    
       for (i = 0; i < num; i++) 
            ar[i] = va_arg(valist, int);
       va_end(valist);
       return ar;
    }
    
    int main()
    {
        int *size=malloc(3*sizeof(int*)),i;
        setarray(size,"1 2 3");
    
        for(i=0;i<3;i++)
            printf("%d\n",size[i]);
    
        setarray2(size,3 ,4,5,6);
        for(i=0;i<3;i++)
            printf("%d\n",size[i]);
    
        return 0;
    }
    

    【讨论】:

    • 你也可以从函数中循环 sscanf 然后返回数组
    • 欢迎来到 Stack Overflow。请尽快阅读About 页面。当您在 6 年后回答一个问题时(并且该问题得到了投票和接受),您必须添加一些独特的东西——一种新颖的方法,或者产品可能在给出原始答案后发生了变化。对您来说幸运的是,其他答案都没有建议解析数组值的字符串表示形式——这样就可以了。我不确定这是一个好的机制,但它是不同的。您对malloc() 的调用未在sizeof(char) != sizeof(int) 所在的任何计算机上分配足够的空间。
    • 编辑过的malloc,如果使用字符串不行,也可以使用stdarg.h中的函数
    【解决方案6】:

    还可以通过使用编译器的结构块副本来隐藏 memcpy。由于所有的 .i 和 i ,它使代码变得丑陋:但也许它可以解决您的特定问题。

    typedef struct {
        int i[3];
    } inta;
    
    int main()
    {
        inta d = {i:{1, 2, 3}};
    
        if (1)
            d = (inta){i:{4, 5, 6}};
    
        printf("%d %d %d\n", d.i[0], d.i[1], d.i[2]);
    
        return 0;
    }
    

    【讨论】:

      【解决方案7】:

      还有这个……:)

      char S[16]="";
      strncpy(S,"Zoodlewurdle...",sizeof(S)-1);
      

      测试如果你声明 S[8] 或 S[32] 会发生什么,看看为什么它如此有效。

      我根据 OpenBSD 的 strlcpy 的逻辑编写了自己的字符串函数,旨在确保在发生溢出时必须存在终止符字节,而标准 strncpy 不会这样做,因此您必须仔细观察如何使用它。

      上面的方法是有效的,因为 ="" at 声明确保整个 0 字节,而 sizeof(S)-1 确保如果你过度使用传递给 strncpy 的带引号的字符串,你会被截断并且不会违反最后一个 0 字节,所以这个现在可以安全地防止溢出,并且稍后访问字符串。我的目标是 ANSI C,所以它在任何地方都应该是安全的。

      【讨论】:

      • 我意识到这是一个字符串,而不是一个整数数组,但可能有一种方法可以相应地翻译该方法,而无需编写自己的迭代代码。
      • strncpy 是字符数组,就像 ___ 是整数数组一样?
      【解决方案8】:

      我会将此作为评论发布,但我没有足够的声誉。初始化数组的另一种(可能是肮脏的)方法是将其包装在结构中。

      #include <stdio.h>
      
      struct wrapper { int array[3]; };
      
      int main(){
          struct wrapper a;
          struct wrapper b = {{1, 2, 3}};
      
          a = b;
      
          printf("%i %i %i", a.array[0], a.array[1], a.array[2]);
      
          return 0;
      }
      

      【讨论】:

        【解决方案9】:

        这在 gcc 下使用 -O3 可以更好地工作和优化(编译器完全删除代码),而 memcpy 在所有情况下都强制复制内存。

        template <typename Array>
        struct inner
        {
            Array x;
        };
        
        
        template <typename Array>
        void assign(Array& lhs, const Array& rhs)
        {
            inner<Array>& l( (inner<Array>&)(lhs));
            const inner<Array>& r( (inner<Array>&)(rhs));
            l = r;
        }
        
        int main()
        {
            int x[100];
            int y[100];
        
            assign(x, y);
        }
        

        【讨论】:

        • 问题标记为 C,而不是 C++。这个答案是 C++,在 C 中完全无效。
        猜你喜欢
        • 2010-10-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-04
        • 2020-01-31
        • 2011-08-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多