请帮助我理解我在此C代码中找到的两件事:
首先,有整个代码:
usbMsgLen_t usbFunctionSetup(uchar data[8])
{
usbRequest_t *rq = (void *)data;
static uchar dataBuffer[4]; /* buffer must stay valid when usbFunctionSetup returns */
if(rq->bRequest == CUSTOM_RQ_ECHO){ /* echo -- used for reliability tests */
dataBuffer[0] = rq->wValue.bytes[0];
dataBuffer[1] = rq->wValue.bytes[1];
dataBuffer[2] = rq->wIndex.bytes[0];
dataBuffer[3] = rq->wIndex.bytes[1];
usbMsgPtr = dataBuffer; /* tell the driver which data to return */
return 4;
}else if(rq->bRequest == CUSTOM_RQ_SET_STATUS){
if(rq->wValue.bytes[0] & 1){ /* set LED */
LED_PORT_OUTPUT |= _BV(LED_BIT);
}else{ /* clear LED */
LED_PORT_OUTPUT &= ~_BV(LED_BIT);
}
}else if(rq->bRequest == CUSTOM_RQ_GET_STATUS) {
dataBuffer[0] = ((LED_PORT_OUTPUT & _BV(LED_BIT)) != 0);
usbMsgPtr = dataBuffer; /* tell the driver which data to return */
return 1; /* tell the driver to send 1 byte */
}
return 0; /* default for not implemented requests: return no data back to host */
}
现在,usbFunctionSetup
获得8个无符号字符的数组。现在有了这条线:
usbRequest_t *rq = (void *)data;
所以,我得到了声明的左侧,但右边是什么?我知道(void *)
被投射到这种类型,但为什么呢?
第二个问题是,这段代码效率不高吗?因为第一个函数接收8个字节的数据,而不是创建指向它们的附加指针。并且至少在我是对的时候创建了附加指针,只是为了能够通过usbRequest_t
struct中定义的名称访问单个数据。例如,仅仅在代码而不是rq->bRequest == something
中使用会更简单,更高效
data[2]==something
或bRequest
是否大于一个字节,例如data[1] == low_byte_of_something && data[2]== high_byte_of_something
?
答案 0 :(得分:0)
该函数正在获取数据的“原始”缓冲区,以及行:
usbRequest_t *rq = (void *)data;
只是创建一个指向该缓冲区的指针,使用usbRequest_t
结构体指定的数据布局来访问它。
这个操作绝对没什么代价 - 编译器甚至可能不会在优化的构建中实际创建新的指针变量。
另一方面,可能存在可移植性问题,但这对您的特定应用程序可能并不重要。
答案 1 :(得分:0)
问题1:由于data
为uchar *
,您需要将其转换为其他类型。如果您愿意,可以将其直接投射到usbRequest_t *
。
问题2:rq->bRequest
的地址需要花费尽可能多的时间来计算data[2]
的地址。在这两种情况下,您都会从堆栈中取出指针并为其添加固定偏移量。使用struct指针可以产生更清晰的代码。
答案 2 :(得分:0)
您的第一行( rq =(void )..)告诉编译器将传递的8个字节视为usbRequest_t
可能这是来自设备或网络的数据包,代码希望将其视为与结构匹配
是的,它会创建一个指针 - 但在生成的代码中几乎肯定会发生的事情是第一个字节的地址被简单地加载到寄存器中。所以没有开销
相反你的建议rq-> bRequest ==某些东西实际上会复制数据 - 这是一个(v小8字节)开销
这是将结构映射到序列化数据流的一种非常常见的技术
答案 3 :(得分:0)
关于您声称代码效率低下的说法,我发现访问data[x]
和rq->x
之间几乎没有区别。在这两种情况下,代码都以base-address开头,并且偏移几个字节(显然最多为8个字节)。
[Base Address] + [Offset]
将是相同的,无论你是按阵列还是按结构来做。如果简单的添加是程序效率低下的根源,那么你就会遇到更大的问题。