【问题标题】:Initializing mixed types (constants) in a void* structure - is it possible?在 void* 结构中初始化混合类型(常量) - 可能吗?
【发布时间】:2013-01-27 09:02:27
【问题描述】:

当我将单个元素初始化为 void 结构时,它可以正常工作:

void* CMD_ARRAY[] = 
{
  {"+++\r"},
  {"+++\r"},
  {"+++\r"},
};

但是,当我尝试向结构中添加更多元素时,即:

void* CMD_ARRAY[] = 
{
  {"+++\r" ,  4,  1300},
  {"+++\r" ,  4,  1300},
  {"+++\r" ,  4,  1300},
};

这会导致错误:

预期为“}”

第一个示例中的单个元素与结构的结构(也被视为元素)之间有什么区别?

如何实现这种混合类型的 void 结构的初始化?

更新: 所以我知道编译器不知道如何处理相同元素中的不同类型。有没有办法动态定义这些类型(即使用强制转换)而不实际定义此定义之外的结构(即使用结构数组)?

【问题讨论】:

  • “第一个例子中的单个元素和结构的结构有什么区别...” 区别在于你没有告诉编译器它们的类型是什么。它不能只是猜测
  • 我知道还有其他方法(即定义结构),但如果我能以这种方式实现它,它将解决我的问题。
  • @user2015194 你的问题到底是什么?我想说不管是什么,都有比这种方法更好的方法来解决它。

标签: c struct void-pointers


【解决方案1】:

我建议编译器无法猜测有关您的隐式结构声明的某些细节。例如,您的编译器如何猜测我希望下面示例中的 yshort

struct foo { char *x; short y; unsigned int z; };

void* CMD_ARRAY[] = 
{
  &(struct foo){"+++\r" ,  4,  1300},
  &(struct foo){"+++\r" ,  4,  1300},
  &(struct foo){"+++\r" ,  4,  1300},
};

这可以以易读为代价扩展为:

void* CMD_ARRAY[] = 
{
  &(struct { char *x; short y; unsigned int z; }){"+++\r" ,  4,  1300},
  &(struct { char *x; short y; unsigned int z; }){"+++\r" ,  4,  1300},
  &(struct { char *x; short y; unsigned int z; }){"+++\r" ,  4,  1300},
};

edit:除了易读性的成本之外,考虑如果您决定在更高级别更改结构会发生什么。您必须在较低级别进行大量查找/替换。你觉得这听起来很甜蜜吗?

【讨论】:

  • 谢谢!这正是我一直在等待的答案类型。但是,这对 :-( 我已经对 foo 结构进行了 typedef 并收到:不允许强制转换为“foo”类型。我猜是 armcc 编译器问题而不是“C”问题
  • 我只是为了解释为什么扩展实际上是一个坏主意而进行了编辑。请考虑在架构中明确定义需要它的结构的途径。你可以把它放在一个 .h 文件中,包含保护,#include "foo_structs.h" 在你需要的每个文件中。
  • 对不起,这只是糟糕的代码。它使代码变得不必要难以阅读,并且显式声明结构的实例并通过初始化数组来链接它没有任何好处。
  • 我已经说过这是糟糕的代码。这就是问题所要求的。有问题吗?
【解决方案2】:

使用大括号作为初始化器意味着初始化结构化信息。您正在初始化一个空指针数组。所以编译器需要一组指针,他可以存储在这个数组中。您的第二个变体不再是指针,它的长度约为 12 个字节。在单个 void-pointer 数组单元中没有足够的空间。

此外,在查看此代码时,我感到有什么不好的事情正在出现。你到底想做什么?

【讨论】:

  • 我有一个通用设备层,用于激活不同的设备。泛型数据结构定义在接口层,它上面的应用程序可以使用泛型结构(不知道他实际使用的是什么)。此初始化代码来自设备最低层 - 我不想将接口中的定义包含到设备文件中,因此我只想初始化一个普通数据结构,稍后我将指向它作为泛型类型。我希望我足够清楚:-)
  • 其实对我来说还不够清楚。为什么不只在这个列表中存储句柄(实际上是指向设备结构的指针)并在其他地方定义结构?
  • 应用层 -> 使用通用设备类型。接口层 -> 持有指向正确设备结构的指针(众多设备结构之一)。设备层 -> 为每个设备定义特定的结构(不知道存在具有通用类型的更高层)。最终,避免定义结构的原因是我不想将泛型类型从接口级别包含到设备级别,另一方面,我不想将结构定义从一层复制到另一层。
  • @user2015194 好的,不发出像void * DeviceXYHandleGet(int num) 这样的调用返回指向其结构实例的空指针的原因又是什么?您的初始化代码可以将此句柄传递给应用程序,该应用程序将其通过所有层传递到知道如何使用此数据的设备驱动程序?您无需复制结构定义,并且您的软件的其中一个部分需要了解具体设备。
  • 我确实通过传递一个 void 指针来初始化正确的结构。这就是为什么我坚持一个空的结构。这个 void 指针将在上层接口层中转换为泛型类型,无论我从哪个设备收到它......
【解决方案3】:

你有一个指针数组而不是结构数组。文字字符串初始化器是可以分配给 void 指针的单个指针,要使用结构化初始化器,它必须分配给匹配的结构 - 否则编译器如何知道将数据放在内存中的位置?

【讨论】:

  • 那么我怎么能告诉编译器他有一个指向结构的指针数组(实际上没有在这个定义之外定义结构)?
  • @user2015194 你遇到了另一个严重的问题:你怎么知道以后的结构是什么样的? - 我会说你的设计没有经过深思熟虑
  • 我在更高层有一个定义。但是这种结构用于较低层(不“知道”较高层的存在......)
  • 这里的解决方案似乎很简单:把定义放在低层。
  • 所以你的“设计”颠倒了!?虽然您可以避免指针引用任何对象,但您不能将其初始化为就好像它是特定对象一样。要么定义必须在较低级别,要么初始化必须由较高级别执行。您也许可以为此使用回调。
猜你喜欢
  • 1970-01-01
  • 2018-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-25
  • 2015-11-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多