Search code examples
carduinoembeddedatmega

Pointer to an element inside a structure ( C )


For the arduino platform, I want to receive 16 bytes and stuff their value inside a structure. Currently I have this code in place

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 ) ;
}

The struct 'Sections' does not exist yet but it will contain 16 variables of uint8_t type. Though this will propably work just fine, I prefer to use a for-loop.

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 ) ;
}

I am not new to pointers, but I have not used this particular example yet and better safe than sorry.

My qeustion: Am I making correct use of the pointer in this example? And if not, how should it look like?

An awnser with just "yes" suffices for me. Thanks in advance.

EDIT: I am aware of structure padding in storage, the struct will be containing precisely 16x uint8_t variables. However it may be a problem that the compiler may re-arrange the storage of the struct's variables in a random order.

Also important thing I perhaps should have mentioned. It is not in the example. But that function storeLayout( &newSection ) will copy the content of this local structure to a structure object which is part of an array.

So there will be an array of 64 of these structures (each containing the 16 uint8_t variables)

Are there ways to use the this example for-loop without having to turn it's variables in an array instead? (to deal the random compiler behaviour for variable storage)


Solution

  • i think your path is correct your code it's ok

    you can see this answer for sending and receiving Packet

    and the following example show how to point to a item of struct

    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;
    

    and if you want ignore padding in structs add the following code

    #pragma pack(push, 1)
    
    // define your structs
    typedef struct {
        uint16_t X;
        uint8_t  Y;
        uint8_t  Z;
    } PacketNoPadding;
    
    #pragma pack(pop)
    

    you can see result with print sizeof(Packet)

    • remember there is no padding in 8bit system such as Arduino UNO or AVR, but padding in ARM MCU is exists