我对C缺乏经验,并且在微控制器上工作,消息存储在数组中,每个字节都有不同之处。如何为数组的每个元素赋予一个人类可读的名称,而不是将它们引用为msg [1],msg [2]等?
结构是什么意思?但是“你不能对结构的二进制布局做出假设,因为它可能在字段之间有填充。”
我应该只使用这样的宏吗? (我知道“宏很糟糕”,但代码已经充满了它们)
#define MSG_ID msg[0]
#define MSG_COMMAND msg[1]
哦!或者我想我可以做到
MSG_ID = 0;
MSG_COMMAND = 1;
MSG[MSG_ID];
如果有点丑陋,那可能会更好。
答案 0 :(得分:3)
如果你想走这条路线,肯定会使用一个宏,但要比你建议的更好:
#define MSG_ID(x) (x)[0]
#define MSG_COMMAND(x) (x)[1]
这将允许代码以有意义的方式命名数组,而不是使用宏的方式。
否则,您可以为索引定义常量(抱歉,我无法为它们提供更好的名称......):
#define IDX_MSG_ID 0
#define IDX_MSG_COMMAND 1
如果负责任地使用宏,那么宏也不错。这种“简单别名”是宏可以帮助使代码更容易阅读和理解的情况之一,前提是宏被正确命名并且记录良好。
编辑:根据@Lundin的评论,提高代码可读性和安全性的最佳方法是引入类型和一组函数,如此(假设您存储在{{1}中并且消息为char
长):
MESSAGE_SIZE
这种方法虽然带来了某种程度的类型安全性并允许您从使用中抽象出存储,但也引入了调用开销,这在微控制器世界中可能会有问题。编译器可能通过内联函数来减轻其中的一部分(您可以通过在定义中添加typedef char MESSAGE[MESSAGE_SIZE];
char get_message_id(MESSAGE msg) { return msg[0]; }
char get_message_command(MESSAGE msg) { return msg[1]; }
关键字来激活这些函数。)
答案 1 :(得分:2)
在C中命名一组整数的最自然的概念是枚举:
enum msg_pos { msg_id, msg_command, };
默认情况下,它们从0
开始计数并递增1。然后,您可以通过msg[msg_id]
访问字段。
答案 2 :(得分:1)
如果花时间弄清楚编译器如何将它们排出,那么使用结构是很好的,结构在嵌入式编程中非常有用。它将始终按顺序布置成员,但如果您不使用8位微处理器,则可能存在填充。 GCC有一个“packed”属性,你可以应用于struct来禁止填充,而其他一些编译器也有类似的功能。