Vitalii
Vitalii

Reputation: 19

Different behavior for \" in C

I have a strange problem when using string function in C. Currently I have a function that sends string to UART port. When I give to it a string like

char buf[32];
strcpy(buf, "AT+CPMS=\"SM");
strcat(buf, "\"");
uart0_putstr(buf);
//or 
uart0_putstr("AT+CPMS=SM");  //not a valid AT command, but without quotes just for test

it works well and sends string to UART. But when I use such call:

char buf[32];
strcpy(buf, "AT+CPMS=\"SM\"");
uart0_putstr(buf);
//or
uart0_putstr("AT+CPMS=\"SM\"");

it doesn't print to UART anything. Maybe you can explain me what the difference between strings in first and second/third cases?

Upvotes: 2

Views: 130

Answers (3)

Peter - Reinstate Monica
Peter - Reinstate Monica

Reputation: 16016

First the C language part:

  • String literals: All C string literals include an implicit null byte at the end; the C string literal "123" defines a 4 byte array with the values 49,50,51,0. The null byte is always there even if it is never mentioned and enables strlen, strcat etc. to find the end of the string. The suggestion strcpy(buf, "AT+CPMS=\"SM\"\0"); is nonsensical: The character array produced by "AT+CPMS=\"SM\"\0" now ends in two consecutive zero bytes; strcpy will stop at the first one already. "" is a 1 byte array whose single element has the value 0. There is no need to append another 0 byte.
  • strcat, strcpy: Both functions always add a null byte at the end of the string. There is no need to add a second one.
  • Escaping: As you know, a C string literal consists of characters book-ended by double quotes: "abc". This makes it impossible to have simple double quotes as part of the string because that would end the string. We have to "escape" them. The C language uses the backslash to give certain characters a special meaning, or, in this case, suppress the special meaning. The entire combination of backslash and subsequent source code character are transformed into a single character, or byte, in the compiled program. The combination \n is transformed into a single byte with the value 13 (usually interpreted as a newline by output devices), \r is 10 (usually carriage return), and \" is transformed into the byte 34, usually printed as the " glyph. The string Between the arrows is a double quote: ->"<- must be coded as "Between the arrows is a double quote: ->\"<-" in C. The middle double quote doesn't end the string literal because it is "escaped".

Then the UART part: The internet makes me believe that the command you want to send over the UART looks like AT+CPMS="SM", followed by a carriage return. The corresponding C string literal would be "AT+CPMS=\"SM\"\r".

The page I linked also inserts a delay between sending commands. Sending too quickly may cause errors that appear only sometimes.

The things to note are :

  • The AT command syntax probably demands that SM be surrounded by quotes on both sides.
  • Additionally, the protocol probably demands that a command end in a carriage return.

Upvotes: 3

Vitalii
Vitalii

Reputation: 19

Thanks all. Finally It was resolved with adding NULL char to the end of string.

Upvotes: -1

John Bollinger
John Bollinger

Reputation: 180286

This ...

char buf[32];
strcpy(buf, "AT+CPMS=\"SM");
strcat(buf, "\"");

... produces the same contents in buf as this ...

char buf[32];
strcpy(buf, "AT+CPMS=\"SM\"");

... does, up to and including the string terminator at index 12. I fully expect an immediately following call to ...

uart0_putstr(buf);

... to have the same effect in each case unless uart0_putstr() looks at bytes past the terminator or its behavior is sensitive to factors other than its argument.

If it does look past the terminator, however, then that might explain not only a difference between those two, but also a difference with ...

uart0_putstr("AT+CPMS=\"SM\"");

... because in this last case, looking past the string terminator would overrun the bounds of the array, producing undefined behavior.

Upvotes: 2

Related Questions