【问题标题】:Pointer to an element inside a structure ( C )指向结构内元素的指针 (C)
【发布时间】:2021-02-02 23:34:32
【问题描述】:

对于 arduino 平台,我想接收 16 个字节并将它们的值填充到一个结构中。目前我有这段代码

if( Serial.available() >= sizeof( newSection ) ) { // if atleast one full struct is received

    Sections newSection ;                   // declare a local Sections object and fill it
    
    newSection.leftSensor = Serial.read() ;
    newSection.leftSensor = Serial.read() ; // the other variables don't exist yet
    newSection.leftSensor = Serial.read() ;
    newSection.leftSensor = Serial.read() ;
    newSection.leftSensor = Serial.read() ;
    newSection.leftSensor = Serial.read() ;
    newSection.leftSensor = Serial.read() ;
    newSection.leftSensor = Serial.read() ;
    newSection.leftSensor = Serial.read() ;
    newSection.leftSensor = Serial.read() ;
    newSection.leftSensor = Serial.read() ;
    newSection.leftSensor = Serial.read() ;
    newSection.leftSensor = Serial.read() ;
    newSection.leftSensor = Serial.read() ;
    newSection.leftSensor = Serial.read() ;
    newSection.leftSensor = Serial.read() ;
    
    storeLayout( &newSection ) ;
}

结构“Sections”尚不存在,但它将包含 16 个 uint8_t 类型的变量。虽然这可能工作得很好,但我更喜欢使用 for 循环。

if( Serial.available() >= sizeof( newSection ) ) { // if atleast one full struct is received

    Sections newSection ;                   // declare a local sectuin variable and fill it
    
    uint8_t *ptr ;
    ptr = &newSection.leftSensor ;          // let pointer point to the first variable of local struct object < -???
    
    for( byte i = 0 ; i < sizeof( newSection ) ; i ++ ) {
        *ptr = Serial.read() ;
        ptr ++ ;
    }
    
    storeLayout( &newSection ) ;
}

我对指针并不陌生,但我还没有使用过这个特定的例子,而且比抱歉更安全。

我的问题:我在这个例子中正确使用了指针吗? 如果不是,它应该是什么样子?

只有“是”的遮阳篷对我来说就足够了。 提前致谢。

编辑: 我知道存储中的结构填充,该结构将包含精确的 16x uint8_t 变量。但是,编译器可能会以随机顺序重新安排结构变量的存储,这可能是一个问题。

我也许应该提到的也是重要的事情。它不在示例中。但是该函数 storeLayout( &newSection ) 会将这个本地结构的内容复制到一个结构对象中,该结构对象是数组的一部分。

因此会有一个由 64 个这些结构组成的数组(每个包含 16 个 uint8_t 变量)

有没有办法使用这个例子的for循环而不用把它的变量转换成一个数组? (处理变量存储的随机编译器行为)

【问题讨论】:

  • "它将包含 16 个变量" 你听说过数组吗?当您可能考虑使用一个时,就是这种情况。数组是为这种东西设计的。不要为指针算术而烦恼。 newSection.leftSensor[i]= Serial.read(); 就是你所需要的。
  • 不清楚您的问题是什么,但struct Sections { uint8_t leftSensor[16]; }; 将允许您循环超过 16 个元素。您的第一个代码块令人费解;您覆盖同一个位置 16 次,这似乎没有效率。
  • @JonathanLeffler 这只是例子,先生,OP 试图展示分配给单个成员的方法。
  • 否;结构的元素必须按照声明的顺序分配,可能在元素之间或最后一个元素之后进行填充,但在第一个元素之前不允许填充。不允许重新排列。 (参见 C11 §6.7.2.1 Structure and union specifiers ¶15 和 ¶17。)
  • 即使没有填充和重新排序元素,使用指针算法指向指针指向的数组之外也是非法的。对于此定义,具有非数组类型的变量计为具有 1 个元素的数组,并且不允许在最后一个元素之后使用超过 1 个元素的指针算术。

标签: c arduino embedded atmega


【解决方案1】:

我认为你的路径是正确的你的代码没关系

你可以看到this发送和接收数据包的答案

下面的例子展示了如何指向一个结构体

typedef struct {
    uint16_t X;
    uint8_t  Y;
    uint8_t  Z;
} Packet;

Packet mPacket;

uint8_t* pY = &mPacket.Y;
uint16_t* pX = &mPacket.X;

// point to whole struct and cast it to byte array 
uint8_t* pPacketBytes = (uint8_t*) &mPacket;

如果您想忽略结构中的填充,请添加以下代码

#pragma pack(push, 1)

// define your structs
typedef struct {
    uint16_t X;
    uint8_t  Y;
    uint8_t  Z;
} PacketNoPadding;

#pragma pack(pop)

你可以通过 print sizeof(Packet) 看到结果

  • 记住在 8 位系统(如 Arduino UNO 或 AVR)中没有填充,但在 ARM MCU 中存在填充​​li>

【讨论】:

  • 这没有回答问题。
猜你喜欢
  • 1970-01-01
  • 2017-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-11
  • 2012-07-16
  • 2021-07-14
  • 1970-01-01
相关资源
最近更新 更多