-1

I am trying to assign string to uint8_t buffer in IAR, but I get a warning message.

rx_buffer.rx_struct.RESP.RESPOND is struct field of uint8_t type.

My code is:

strncpy(rx_buffer.rx_struct.RESP.RESPOND, (uint8_t *)'NS,', 3);

And the associated warning message is the following:

Warning[Pe1422]: multicharacter character literal (potential portability problem) 
Warning[Pe167]: argument of type "uint8_t *" is incompatible with parameter of type "char *",
Warning[Pe167]: argument of type "uint8_t *" is incompatible with parameter of type "char const"

I have written a workaround :

rx_buffer.rx_struct.RESP.RESPOND[0] = 'N';
rx_buffer.rx_struct.RESP.RESPOND[1] = 'S';
rx_buffer.rx_struct.RESP.RESPOND[2] = ',';

But I'm not satisfied with it. What is the correct way to do that?

chqrlie
  • 131,814
  • 10
  • 121
  • 189

3 Answers3

4

Your code is incorrect in many ways:

strncpy(rx_buffer.rx_struct.RESP.RESPOND, (uint8_t *)'NS,',3);
  • The destination array does not have type char *
  • the source is not an array: 'NS,' is a multicharacter character constant, a non portable historic oddity that nobody would use in any decent code... casting it to (uint8_t *) does not fix this issue. You should just use double quotes: "NS,".
  • strncpy() is not the proper tool for this job. In fact it is never the right tool for any job. This function is not a safe replacement for strcpy, it semantics are widely misunderstood, it is very error prone. You should avoid using this function. In this particular case, it would just copy the 3 bytes as expected, but why use strncpy() when memcpy() is a simpler solution?

You can achieve your goal with this:

memcpy(rx_buffer.rx_struct.RESP.RESPOND, "NS,", 3);

or alternately by assigning each byte separately as posted in the question. Both approaches are likely to produce the same machine code.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
2

You are using single quotes but you need double quotes ("NS,") , and take a look to Stop using strncpy already!, in this case it should work as expected because you don't want the trailing '\0', but don't use it.

Use memcpy or memmove, also (as a question of style) don't use magic numbers like 3:

#include <stdio.h>
#include <string.h>
#include <stdint.h>

#define MAX_SIZE 3

int main(void)
{
    uint8_t arr[MAX_SIZE];

    memmove(arr, "NS,", MAX_SIZE);
    for (int i = 0; i < MAX_SIZE; i++) {
        printf("%c", arr[i]);
    }
    printf("\n");
    return 0;
}
David Ranieri
  • 39,972
  • 7
  • 52
  • 94
0

strncpy expects its first two arguments to be of type char * and const char *, respectively. Instead of casting to unit8_t *, you should be casting to char *, if at all.

Also, 'NS,' is a character literal, a string literal would be "NS,".

Dmitry Grigoryev
  • 3,156
  • 1
  • 25
  • 53