When a stuct char is ..not a char anymore?

This particular library (mavlink) expects "const char * param_id"
Screenshot from 2023-01-29 15-56-20

const char test2_id[] = "TEST2";
struct stParameters {
  const char name[5];
  uint8_t value;
  uint8_t type;
  bool writable;
};
struct stParameters mavParameters[] = {
  { "TST1", 10, MAV_PARAM_TYPE_UINT8, true },
  { "TST2", 20, MAV_PARAM_TYPE_UINT8, true }
};


If I simly call it using "test2_id" like:
mavlink_msg_param_value_pack(SYS_ID, COMP_ID, &msg, test2_id, param.value, ....
then it works ..just as expected.

but when I get the parameters from struct like:
struct stParameters param = mavParameters[i];

and call it like:
mavlink_msg_param_value_pack(SYS_ID, COMP_ID, &msg, param.name, param.value, ....

  • then something bad happens, the packet is not ok. it is hard to tell what goes wrong. - it compiles - but does not work.
    (to test - it needs to speak to ground control software and autopilot)

Please note that param.name works fine ... but not the char array,
What is it that I do goes so strangely wrong?

Perhaps because const string is "TEST2"

but param.name is "TST2" ?

are you missing ending nulls?
string should be terminated, pretty sure it happens automatically with the way you declared test2_id but not in the struct, but you do got the room for 1 more char add a null /0 to TST1 and TST2.
good luck..

No the name is just an example, I can send any null-terminated text up to 16chars.
the point of using char was exactly that they are null-terminated.
It seems there is something else going wrong here..but I do not understand what .. wish I had python's type() function to dig into it..

Please show your full code or at least minimal representative example, that others can try with their boards.

There is no way for you to reproduce it unless you hook it up with an autopilot and ground station.
The three first lines is the transmitted MAVlink packet that uses direct variable for "SW_VER"
The last three lines is the packet for when SW_VER comes from the table. - both seem ok,and 0x0 terminated except for ..the second packet's payload fails.

Screenshot from 2023-01-29 16-45-05

I cannot expect perfectly equal packets - because the last bytes are checksum, and there is a sequence number in the beginning.
After much testing .. this is what I find ... using param.name fails. - for unknown reason.

can you just mark the sequence numbers and checksums please.
preferably test_id is the same as whats in the struct.

Try with


struct stParameters {
  const char * name;
  uint8_t value;
  uint8_t type;
  bool writable;
};

 stParameters mavParameters[] = {
  { "TST1", 10, MAV_PARAM_TYPE_UINT8, true },
  { "TST2", 20, MAV_PARAM_TYPE_UINT8, true }
};
1 Like

Thank you. That's an improvement - it did not solve the issue, but facilitated variable name-length.

Another interesting issue that proves the difference between a "real" char vs one via the struct:

const char test_id[] = "TEST";

struct stParameters {
  const char * name;
  uint8_t value;
  uint8_t type;
  bool writable;
};
struct stParameters mavParameters[] = {
  { "TST1", 10, MAV_PARAM_TYPE_UINT8, true },
  { "TST2", 20, MAV_PARAM_TYPE_UINT8, true }
};
  
 struct stParameters param = mavParameters[1];
 Serial.println(test_id[2]);
 Serial.println(param.value[2]);

The last line will fail compilation with:
Compilation error: invalid types 'uint8_t {aka unsigned char}[int]' for array subscript
Maybe this somehow "proves" that param.value is somehow different, or contains something more than it should?

Your param.value field declared as single uint8_t variable, what does you mean when call it as array?

IDK. :slight_smile: Maybe the function/library somehow gets confused by exactly that ? it is expecting char array.
That's the issue here.. I do not know exactly why this do not work. - trying to understand it .. I would expect param.value[2] to be accessible ... just like a char[2] would be ... if the stuct-way was completely transparent.

Why do you expect this?

Let's for example a single variable

byte x;

What do you expect to see with line:

print( x[2] );

By the way, could you show the result of the expression:

sizeof(param)

depending on the length of the string stored in the name field?

I guess you mean param.name:

const char swvr_id[] = "SWVR";
        Serial.print(" name:");
        Serial.print(param.name);
        Serial.print(" sizeofname:");
        Serial.print(sizeof(param.name));
        Serial.print(" sizeofvar: ");
        Serial.println(sizeof(swvr_id));

Output:
name:TST1 sizeofname:4 sizeofvar 5

... hmm not five chars ? - no 0x0 termination anymore?
you are definitely onto something .. the termination character is gone.. - but how to fix that?

Does the compiler throw an error, or is the error at run-time?
Could the problem be that param.name is a local variable, that may be overwritten with random data before it is actually used by the library?

this makes param equal 1 record, TST2, just use param.value, param is not an array.

sizeof is reporting size of char pointer not how long array is.

size of param is 5, size of param.name is 2.

i was hoping it was as easy as "TST1" to "TST1\0" and "TST2" to "TST2\0" but must be something else..
sorry..

1 Like

Yes, I am disappointed that getting param.name from a struct is disregarding const char name[5];
In fact, I find it frightful - I thought that structures were a neat way to organize things, not to mess them up.

Now that we narrowed it down, it remains to figure out a way of fixing this.

@AndreK
Does this also not works?

#define NAME_SIZE 8
struct stParameters {
  char name[NAME_SIZE];
  uint8_t value;
  uint8_t type;
  bool writable;
};

 stParameters mavParameters[] = {
  { "TST1\0", 10, MAV_PARAM_TYPE_UINT8, true },
  { "TST2\0", 20, MAV_PARAM_TYPE_UINT8, true }
};

Note that NAME_SIZE should be at least two byte more than the length of the longest name string in Parameters array

That was not a compiler issue, more a programming issue :wink:

What happens if you do
mavlink_msg_param_value_pack(SYS_ID, COMP_ID, &msg, mavParameters[i].name, param.value, ....

Pilot Error, actually.