A quick, little orientation to C strings
The char
type means one character, like one letter. Itâs a single byte. In C, single quotes surround characters, while double quotes surround strings. Single and double quotes are NOT interchangeable like they are in ruby, python, php, etc.
char oneCharacter = 'x';
Adding an asterisk makes the variable a pointer to a char
. On a 32-bit architecture like the Spark Core, the address, the pointer, is 4 bytes long.
char *aString = "x";
In the above expression, the value of aString
is some memory addressâthe memory address where the string starts. The value of *aString
(which can be read as "the thing pointed to by aString
") is the single character 'x'
.
If we only know the address where the string starts, how can tell how long the string is?
C strings are ânull terminatedâ. That means that thereâs always an extra hidden '\0'
character at the end of the string, which is how the machine knows where the string ends and how long the string is.
This is important to recognize! In the above expression *aString
actually takes up 2 bytes: first the 'x'
then the '\0'
. That means that if youâre reserving memory for a string, you always need one more byte than you might think; to hold a string thatâs 10 characters long, you need 11 bytes.
You can find out how long a C string is with strlen()
(strlen newlib docs).
char *aString = "x";
strlen(aString); // returns 1
A common way to break your firmware is to try to write past the end of the memory youâve reserved. Sometimes this causes a hard fault (SOS red flashing), but often it will quietly succeed, overwriting something else you did not expect to change.
The String class hides some of the complexity. Check out its documentation. When you need to get access to the internal C string wrapped up inside the String object, use its c_str()
method.
String cppStringObject = "Why hello!";
char *cString = cppStringObject.c_str();
And remember, this is open source! The String class isnât that scary. In addition to the Spark documentation, you can look at the source to understand how it works. As is usual with C++ classes, the String class is defined in a header file and an implementation file.
You usually reserve (or âallocateâ) memory for a C string at the top of your program.
char message[100];
That expression is an array of characters. Also, perhaps a little confusingly, message
is a pointer to a char
. Itâs just like char *message;
except that the bracket syntax actually reserves space for the string in memory.
To refer to the first character of the string, youâd say message[0]
, and to refer to the second character message[1]
. Thatâs just like most web languages. This is totally fine syntax:
char message[8];
message[0] = 'H';
message[1] = 'i';
message[2] = '!';
message[3] = '\0';
Pretty verbose though.
You would usually instead use strcpy()
(strcpy newlib docs) to change the contents of a character array.
char message[50];
strcpy(message, "Hello world!");
Cheers!