动态更改指向结构的指针数组的数据类型

Posted

技术标签:

【中文标题】动态更改指向结构的指针数组的数据类型【英文标题】:Dynamically change the data type of an array of pointers to a struct 【发布时间】:2018-11-15 09:29:48 【问题描述】:

我正在尝试对结构中的变量指针数组进行编码。我的问题是结构内的变量具有不同的数据类型。

#include "stdlib.h"

typedef struct val 
 unsigned char a;
 unsigned char b;
 unsigned short c;
 unsigned int d;
 _letters;

void setup() 
 Serial.begin(9600);


int var1 = 0;

void loop() 
 _letters lt;
 lt.a = 1;
 lt.b = 2;
 lt.c = 3;
 lt.d = 4;

 unsigned char *ptrLetters[4];
 ptrLetters[0] = &lt.a;
 ptrLetters[1] = &lt.b;
 ptrLetters[2] = &lt.c;   //here is the problem
 ptrLetters[3] = &lt.d;  //also here

 var1 = (int)*ptrLetters[0];

 Serial.println(var1);

这样做的目的是因为我想保存地址并通过数组的索引(*ptrLetters[index])从结构中访问变量(我不能修改),但问题是里面该结构有不同的数据类型,并且指针仅针对 char 类型进行初始化。 如何动态更改它?

【问题讨论】:

旁注:ptrLetters 对于 4 个元素来说太小了。 注意:在 C 中,当大小为 n 时,数组索引来自 0..n-1。所以对于大小3,索引是0..2 所以你需要一个4 的数组作为索引0..3 您确定不能使用指向该类型结构的单个指针,然后将其取消引用到您要检索或写入的任何元素吗?我不明白为什么需要一个 array 指针... 【参考方案1】:

指向任何类型对象的指针可以隐式转换为pointer to void(可选cv-qualified);指针值不变。需要static_cast 或显式转换的反向转换会产生原始指针值:

void *ptrLetters[4];
ptrLetters[0] = &lt.a;
ptrLetters[1] = &lt.b;
ptrLetters[2] = &lt.c;   //no more problem
ptrLetters[3] = &lt.d;  //no more problem here as well

对于取消引用,在 C 中你可以简单地这样做:

unsigned char var1 = *((char*)ptrLetters[0]);
unsigned char var2 = *((char*)ptrLetters[1]);
unsigned short var3 = *((unsigned short*)ptrLetters[2]);
unsigned int var4 = *((unsigned int*)ptrLetters[3]);

因为你也用 C++ 标记了它,所以最好在 C++ 中使用static_cast

unsigned char var1 = *(static_cast<unsigned char*>(ptrLetters[0]));
unsigned char var2 = *(static_cast<unsigned char*>(ptrLetters[1]));
unsigned short var3 = *(static_cast<unsigned short*>(ptrLetters[2]));
unsigned int var4 = *(static_cast<unsigned int*>(ptrLetters[3]));

【讨论】:

在结构中我只有 char 和 short 数据类型(不介意上面是一个例子),如果我只想要 short 数据类型,如何将 char 转换为 short? 您的意思是要将char 变量分配给short 变量? 是的,当我从指针数组中读取值时必须是一个短变量 charshort 提升会保留该值,因此您可以将 char 分配给 short 变量【参考方案2】:

您可以使用 void(无类型)指针数组:

void *ptrLetters[4];
ptrLetters[0] = &lt.a;
ptrLetters[1] = &lt.b;
ptrLetters[2] = &lt.c;   //here is the problem
ptrLetters[3] = &lt.d;  //also here

然后你可以像这样访问你的变量:

var1 = *((char*)ptrLetters[0]);

请注意,您必须首先将 void 指针转换回 original 类型以解除引用。然后在赋值时隐式执行到 int 的转换。

【讨论】:

【参考方案3】:

您没有解释太多为什么要只使用指针数组或为什么要使用指针。根据您在示例代码中尝试执行的操作,您可以通过多种方式进行操作。

最简单的方法是使用指向结构的指针:

_letters *ptrLetter;
ptrLetter = &lt;

var1 = ptrLetter->a;

您还可以探索指针结构或使用 C++ 类将数据和指针一起包含。

【讨论】:

我需要使用这种方法,因为我在没有任何通信协议的产品上实现了 modbus,因此,要通过数字访问结构的变量,使用数组更容易指针。当 modbus 收到索引(数字)和值时,使用指针数组我可以轻松地指向结构中的值并更改内部的值 好的,有道理。如果你想使用基于索引的访问,使用指向结构的指针是行不通的——你应该只按照你的建议使用数组。因此,请使用其他答案中给出的 void 指针数组。

以上是关于动态更改指向结构的指针数组的数据类型的主要内容,如果未能解决你的问题,请参考以下文章

C语言-结构体

C语言数据类型——结构体

C语言数据类型——结构体

初识 go 语言:数据类型

C语言柔性数组

结构数据类型实验