2017-06-04 54 views
8
#define LENGTH 6 
typedef char data_t[LENGTH]; 
struct foo { 
    const data_t data; 
    ... 
} 
... 
void bar(data_t data) { 
    printf("%.6s\n", data); 
    struct foo myfoo = {*data}; 
    printf("%.6s\n", foo.data); 
} 

我试图让这个结构直接保存我感兴趣的数据,sizeof(foo) == 6+the rest而不是sizeof(foo) == sizeof(void*)+the rest。不过,我找不到一种方法来初始化一个foo类型的结构与data_t。我想也许我可以从字段中删除const修饰符并使用memcpy但我喜欢额外的安全性和清晰度。在一个struct中初始化一个const数组

我没有得到任何编译错误,但是当我运行的代码,我得到

123456 
1?? 

因此复制没有正常工作,我想。

这是一个arduino(或类似的设备),所以我试图保持它非常便携的代码。

这难道不可能吗?

编辑:在data_t字段上删除const修饰符似乎没有帮助。

+3

困难在于参数'data_t data'等价于'char * data',并且我没有一个简单的方法可以在卧床休息一小时半后想到。当然,C不支持直接数组赋值。你可以传递'struct foo *'到'bar'吗?然后很简单:'struct foo foo = * data;'。 –

+2

不应该typedef是'typedef char data_t [LENGTH];'? 'struct foo = {* data};'对我来说看起来并不合法...... – InternetAussie

+2

struct foo f {.data = {data [0],data [1],data [2],data [3] ,data [4],data [5]}}' – dasblinkenlight

回答

0

Eehh我找到了一个解决方案。这有点傻,但无论如何

void bar(data_t data) { 
    struct foo myfoo = {0, ...}; // don't initialize the `data` yet, on purpose 
    memcpy((void*)&foo.data, data, LENGTH); 
} 

它没有给出任何警告,我得到保持场上的常量。我知道memcpy对于被认为是const的字段在技术上并不好,但在这种情况下,我只是在初始化该结构的函数中只做了一次。它也似乎是阵列不是一个指针,但实际上完全在foo struct(无指针,yay)里面

如果有人愿意付出,我仍然会喜欢反馈。

+3

如果整个对象不是const和静态的,它很可能会工作,但它是非法的C.如果对象最初声明为const,则不应抛弃指向对象的常量。 – PSkocik

1

以符合标准的方式做到这一点是不可能的。

由于它是constconst char data[6];必须被初始化为可用的,并且它可能只(不具有初始都会自动归零静态对象)来初始化静态,具有字符串字面,或用梅开二度 - 包含初始化程序列表。你不能用指针或其他数组来初始化它。

如果我是你,我会摆脱const,文件.data不应该改变后初始化,然后使用memcpy来初始化它。

const对结构体成员在我看来并不是很好,它有效地防止了你能够拥有初始化函数,而C++通过对它的构造函数提供特殊语言支持来解决问题如果const成员是数组,问题仍然存在)。

1

有可能做到这一点,一些成本>=0

typedef struct 
{ 
    char c[LENGTH]; 
} data_t; // this struct is freely copyable 

struct foo 
{ 
    const data_t data; // but this data member is not 
    int what; 
}; 

void foo (char* x) { 
    data_t d;       // declare freely copyable struct instance 
    memcpy(d.c, x, sizeof(d.c));  // memcpy it 
    struct foo foo = { d, 42 };  // initialise struct instance with const member 
    ... 
}; 

一些编译器(例如,铛)甚至能够优化掉冗余复制(从xd.c,然后从dfoo.data ⇒从x直到foo.data)。其他人(我正在看你的gcc)似乎无法实现这一点。

如果您将指针指向data_t而不是直接指向char指针,则不需要此额外的memcpy步骤。 OTOH为了访问foo中的char阵列,您需要另一级别的成员访问权限(.data.c而不是仅仅.data;尽管如此,它没有运行时间成本)。