A quick, little orientation to C strings
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
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
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.
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, and to refer to the second character
message. That’s just like most web languages. This is totally fine syntax:
message = 'H';
message = 'i';
message = '!';
message = '\0';
Pretty verbose though.
You would usually instead use
strcpy() (strcpy newlib docs) to change the contents of a character array.
strcpy(message, "Hello world!");