Problems understanding char

I am having problems conceptualizing the data type char mainly using an array of char as a string.

I want to transfer sensor numeric data from one photon to another. I know particle.publish only publishes the data type char so using fsprint the data can be cast and published. No problems here.

Now when I subscribe and want to put that data into a defined char variable SG3
with the following statement

char SG3;

and then

SG3=data;

where data is the return from the myHandler function

I get the following compile error

subscribe.ino:150:8: invalid conversion from ā€˜const char*ā€™ to ā€˜charā€™ [-fpermissive]

so does saying ā€¦char SG3; ā€¦ cause SG3 to be a constant? or am i reading the error message wrong?

s

This creates a variable that can hold only one character, not a string of characters. A c-string is an array of characters, so you need to declare your variable like you would for an array,

char SG3[20];

That declaration will create a variable capable of holding 19 characters plus the terminating null character that a c-string needs. You should make that number as large as you need to hold the largest value that data could be.

You can't add characters to a char array that way. There are several methods that can add characters to a char array including snprintf(), strcat(), and strncpy(). Here's an example using strncpy(),

strncpy(SG3, data, sizeof(SG3));
SG3[19] = '\0';

strncpy() will copy, at most, sizeof(SG3) characters (20 in this case), so as long as your data is less than 20 characters, it will work ok. However, if data is longer than 20 characters, it will be truncated, and there would be no terminating null character which will cause problems. Manually setting the last index of SFG3 to the null character will ensure that the string will be properly terminated (even though it might be truncated).

1 Like

Would it be a good idea to replace this with

SG3[sizeof(SG3)] = '\0'

to place the null character at the end of the end of the actual data?

Sure, you could use sizeof(), but you would need to subtract 1 since the last index is 19, and sizeof() wold return 20 in this example. That would make it easier to change the size of SG3, since you would only have to make the change in one place.

SG3[sizeof(SG3) - 1] = '\0';
1 Like

When you declare char SG3[20]; the compiler initializes the 20 locations with zero for you, so you typically don't need to do any more than declare it.

unless the array is on the stack....

I'm not sure what point you're making. Even if the array is zeroed out (only if it's global or static?), it's still necessary to manually add the terminating null if you try to copy more than 20 characters into SG3, correct?

Sorry, I was off the mark here after re-reading this thread.

I guess the point I was trying to make is that only in rare circumstances do I write zero to any allocated memory before using it, which is how I misinterpreted this thread on first read. The only case that comes to mind in the recent pass is managing an array that represented the display buffer for an e-ink display, and then I used memset and set it to 0xff since the display wanted that value.

If you use C string functions on char arrays, you generally get the trailing zero automatically (assuming you started with a legal string). Where folks usually get into trouble is using non-string handling functions on strings and then forgetting to add the trailing zero. The pattern you showed above using strncpy and forcing the trailing zero is great, but strlcpy is the modern way there since strncpy isnā€™t a modern ā€œsafeā€ function in the way snprintf is.

3 Likes

No problem, I was just a little confused about what your point was. Thanks for the reminder about strlcpy(), I was going to check that out to make sure it was available on Particle (not sure which version of C added that), but got side tracked. Actually, I usually do use snprintf() rather than strncpy() because it adds that terminating null.

1 Like