【问题标题】:Simple C array issues简单的 C 数组问题
【发布时间】:2011-01-01 17:16:02
【问题描述】:

#include <stdio.h>

#define MEM_SIZE 16

typedef struct memory_contents{
 unsigned char mem[MEM_SIZE]; /* memory */
} mem;

mem init(char prog[]){
 mem chip = {prog};
 return chip;
}

int main(int argc, char *argv[]){
 char memory[MEM_SIZE] = {0}; /* zero out whole array */
 mem chip = init(memory);

 printf("%d\n", chip.mem[0]);
    return 0;
}

我是否认为这段代码的作用(特别是 init 函数)是尝试将变量“内存”的地址放入结构的数组中? (因此这就是它打印非零值的原因)

我想要实现的是初始化结构,使结构的 mem 数组是 prog[] 参数。这样做的首选或最佳方式是什么?我可以使结构的 mem 指向大小为 MEM_SIZE 的数组的第一个元素的指针,但我觉得这可能会导致问题:如果我稍后在 main 中更改内存数组,它也会更改芯片数组中的值.

【问题讨论】:

    标签: c arrays struct initialization


    【解决方案1】:

    这是推荐的方法:

    #include <stdio.h>
    
    #define MEM_SIZE 16
    
    typedef struct memory_contents{
     unsigned char mem[MEM_SIZE]; /* memory */
    } mem_t;
    
    mem_t* init (char* arr)
    {
        mem_t* info = (mem_t*) malloc (sizeof (mem_t));
        if (!info)
        return NULL:    /* No memory */
    
        memcpy (&info->mem, arr, MEM_SIZE);
        return info;
    }
    
    int main(int argc, char *argv[])
    {
        unsigned char memory[MEM_SIZE] = {1,2,3,4,5,6,0};
        mem_t* chip = init (memory);
        if (!chip)
        return ENOMEM;
    
        printf("values: %d %d\n", chip->mem[0], chip->mem[1]);
    
        if (chip)
        free (chip);
    
        return 0;
    }
    

    还有一点需要注意:尽量不要让结构字段成员名和结构名相同。它们可能会引起很多冲突。

    【讨论】:

    • 是的,我对这两个'mem'不好。 mem_t 中附加的 _t 是否是人们区分类型的公认方式(例如 size_t、time_t)?
    • 这取决于您遵循的编码格式(或准则)。我通常更喜欢这个(通常在很多 *NIX 代码中使用): typedef struct foobar_st {int a;} foobar_t;
    • 不,以_t 结尾的名称是由标准保留的,您可能会在某些时候与操作系统实现发生冲突。所以最好避开它们。
    • 不过,我建议不要使用演员表。
    【解决方案2】:

    您不能更改结构的mem 指针,因为它不是普通指针——名称mem 只是该字段地址的名称。不要使用{ ... } 符号初始化数组;它只是难以阅读和混淆(它肯定让我感到困惑......)。请改用memcpy


    编辑:

    你的代码不能用我的编译器编译:

    error C2440: 'initializing' : cannot convert from 'char []' to 'char'
        This conversion requires a reinterpret_cast, a C-style cast or function-style cast
    

    (错误在这一行:mem chip = {prog};

    起初我对为什么编译您的代码感到困惑,在这里检查之后,这是有道理的:就像我上面所说的,您试图将数组/指针分配给mem,这是不允许的,因为mem 只是数组地址的 name,而不是可以更改的指针。所以你必须使用memcpy 来复制元素。

    【讨论】:

    • 大括号初始值设定项有什么问题——当然,如果使用得当?为什么会让人困惑?
    • here 令人困惑,因为它正在初始化一个数组,而不是一个标量。 (例如:它是给第一个元素赋值吗?还是给整个数组?它甚至可以编译吗?如果没有,是因为你不能给char赋值,还是因为别的原因?它让读者想太多。)出于其他原因,我一般不喜欢它们,但这只是个人品味;不过,在这种特殊情况下,我认为最好避免使用它们。
    • 谢谢 - memcpy 似乎是一个不错的解决方案。我唯一担心的另一个问题是,如果我将 MEM_SIZE 更改为较大的值,复制是否会花费大量时间?
    • 这将花费与任何其他方法相同的时间——复制数组所需的时间。如果要避免复制,请使用指针而不是数组。 :)
    • 显然在这种情况下它是不正确的,因为初始化程序本身是错误的,但听起来您完全不建议初始化数组并始终使用memcpy 来填充它们。
    【解决方案3】:
    1. 使用 memcpy 复制数据
    2. 在func init中分配新的内存,func init结束后“chip”将被回收。

    【讨论】:

      【解决方案4】:

      以上所有方法都是将数据从缓冲区复制到结构中定义的包含缓冲区的推荐方法。

      而且,回答您的问题 - 是的。 您正在使用指针值初始化数组。像在 main 中使用“memory”一样初始化数组: 字符内存[MAX_SIZE] = { 0 }; // 数组初始化。

      执行 memcpy() 是执行此操作的首选方式。另外 - 从函数返回本地结构是不好的做法 - 首选方法是在堆上分配一个对象并执行 memcpy。 (尽管编译器可以优化这一点 - 通过额外的复制)这只是可怕的做法。

      如果你在编译时就知道数组的结构: 其他可能性是 c99 结构初始化(通常在内核模式下完成): mem_t memObj = { .mem = { 1, 2, 3, 4, 5 } }; 或者简单地说: mem_t memObj = { 1, 2, 3, 4, 5 }; (在你的例子中,因为它是唯一的成员)

      注意:在进行数组初始化时,它类似于将数组中的其余元素归零 - 可能不是您期望/想要的。

      【讨论】:

      • 为什么返回本地结构被认为是不好的做法?
      • 从技术上讲 - 你想传入一个结构来填充 ptr/ref。如果从函数返回结构,则复制整个结构对象。
      【解决方案5】:

      对于您的结构,您可以使用隐式 struct-content-copy,例如:

      mem init(char *prog){
       return *(mem*)prog;
      }
      
      int main(int argc, char *argv[]){
       char memory[MEM_SIZE] = {0xAA,0xBB,0xCC,0xDD}; /* non zero test values */
      
       mem chip = init(memory);
       printf("%02X%02X%02X%02X\n",chip.mem[0],chip.mem[1],chip.mem[2],chip.mem[3]);
      
       memory[1]=0;
       chip = init(memory);
       printf("%02X%02X%02X%02X\n",chip.mem[0],chip.mem[1],chip.mem[2],chip.mem[3]);
      
       return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-12-07
        • 2011-05-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-24
        相关资源
        最近更新 更多