C Structure Question

ok, YAY!!!

Norms suggestion is both compiling and giving me results, the ** payload appears to be an issue for me at the moment, but I will be able to get that sorted out now.

the code Eli produced is so much nicer to look at and that might actually only need a tweak to get it working.

so currently Norms code works without modifications as an example of what my original question was aimed at.

I will update with anything more specific to the original question later on.

Thank you to everyone replying, most appreciated.

Are you sure? Norm’s pointer for the array in the middle of the struct made no sense to me. If it is, your data seems not compatible to what was said before.

This is not an error, but a warning. Probably it compiles and run as intended. Not?

Anyway, here is Norm’s and Eli merged in a way the warning should disappear:

#include <stdio.h>

typedef struct {

  char start;

  char address;

  char serialNumber;

  char message[2];

  char payload[21];		// 20 + terminator

} MyMessage;

int main (int argc, const char *argv[]) {

  char array[26] = "abcdefghijklmnopqrstuvwxy\0";

  MyMessage *ptr = (MyMessage *) (&array);

  printf ("start %c\n", ptr->start);
  printf ("address %c\n", ptr->address);
  printf ("serialNumber %c\n", ptr->serialNumber);
  printf ("message %c%c\n", ptr->message[0], ptr->message[1]);
  printf ("payload %s\n", ptr->payload);	// 20 + terminator

  return 0;

}

I found out that the compiler I am using (XC8 from Microchip) does not need PACK as its always aligned due to the 8 bit nature of the target.

yup worked fine

yes a warning, but at this stage in development a warning is as good as an error for me so I never ran the code.

YAY! that works perfectly in my function, thank you very much.

but before you sorted that out I had got another solution to skin this cat:-

    union msg_rx_union
    {
        char *ptr_m;
        //
        struct//structure of the SERIAL RX MESSAGE
        {
            char start;
            char address;
            char msg_ser;
            char msg_type[2];
            char msg_payload[20];
        } *m;
    } msg;
    
    char array[26] = "abcdefghijklmnopqrstuvwxy\0";
    
    msg.ptr_m = (char *)array;
    
    printf ("start %c\n", msg.m->start);
    printf ("address %c\n", msg.m->address);

that compiles, but I have no output for printf as its embedded, so I am testing by loading into a variable and it works fine.

now just have to see what uses lowest byte count into memory and that’s what I will use.

mmm, interesting result in my test between Ricks code and the union version I ended up with.

the union code uses 6 bytes less RAM and 28 bytes less code space, so must for some reason be more efficient in this particular compiler.

You are using Union wrongly. Your ptr_m pointer, if using a 4 byte pointer, probably is sharing memory used by

char start;
char address;
char msg_ser;
char msg_type[2];

And destroying its contents when you assign some value to it.

yes, I want it to ‘destroy’ the structure elements by sharing its address with the pointer.
they basically have the same start address which is exactly what I was trying to get.

the pointer in the union is the same type as the array I am receiving, this appears in my compiler to cause no issue in operation of the code and I have the expected results.

I do not know if this code would be a danger in a PC app, but this is running in an 8 bit chip that has severe restrictions in memory management.
I have used a union in this way for years in lots of projects using this same compiler and it does what I was trying to do here, basically give the same address to the structure as the data array I create.

if it is unsafe I would appreciate a greater understanding of why.
if I have to change the existing code I would be happy to do so.

as it stands now, I recover all the data I expect to recover and, the pointer, however it is handled by this compiler, does not overwrite the data in the structure.

other uses I have is to efficiently split a signed 32 bit value into 4x8 bit values that are stored in a EEPROM which only has 8 bit elements.

union
    {
        int32 v32b;//the 32 bit value to be split up
        uint8 b[4];//an array which will hold the individual data bytes
    } sb;//the name of the union

    sb.v32b = w_data;//load the 32 bit value into the union

‘w_data’ is a 32 bit signed value which places the 4 bytes in the array.

that code is 10 years in use at least, maybe I am relying on some quirk of this compiler for it to work?

I am thinking about why the code I am using works and I don’t know really.

as Rick suggests, the pointer SHOULD corrupt the data but it does not, I think this I some special way that the XC8 compiler handles pointers due to it being purely an 8 bit compiler.

You are not wrong, it’s not usual what you did instead of doing a cast of pointers, but my “destroying” argument was because, for one moment, I read the union as a struct and a pointer and not 2 pointers.

ah, ok, thank you.

both pointers is good, I see, so there is no corruption as everything in the union has the same type defined.

Yep. You did a “weird pointer casting” but nothing really wrong. :grin:

haha, and I never even knew it, it works and I am very pleased.