Additional standard functions

The C “standard” libraries include a number of functions not featured by the main Arduino documentation. They are listed here with short notes on their usage.

It is also worth mentioning that there are some synonyms for integer data types that are often used in sample code. After all, you might want to declare a 16 bit int that will still be 16 bits if the code is compiled for a 32 bit Arduino. You can be specific with int8_t, int16_t, int32_t and int64_t where the number defines the number of bits used for a signed integer type. Similarly, uint8_t, uint16_t, uint32_t and uint64_t define the bit length of unsigned integer types. The type size_t is the unsigned integer type returned by the sizeof() function although the bit width is system dependent.

There are also some useful macros in the form INTn_MIN, INTn_MAX and UINTn_MAX that define the minimum and maximum values that can be stored in a specific int type where n is the relevant number of bits. These can be handy for initialising variables at one extreme or the other.

The limits.h library also has definitions for values such as INT_MAX or LONG_MIN and these values are adjusted for the appropriate board at compile time.

<string.h>

This library contains many useful functions for manipulating char arrays. Many of these together with number conversion functions from stdlib.h are re-packaged by the Arduino String object.

char *strcpy(aStr, bStr) copies string bStr to string aStr, returns a pointer to aStr.
char *strncpy(aStr, bStr, n) copies n chars from string bStr to string aStr and pads with char ‘\0’ if bStr has less than n chars.
char *strcat(aStr, bStr) concatenates string bStr to the end of aStr, returns a pointer to aStr. This is managed by inserting the chars in bStr from the terminating null char in aStr. The char array containing aStr must be large enough to accept the string bStr.
char *strncat(aStr, bStr, n) concatenates up to n chars from bStr to aStr. terminates aStr with ‘\0’
int strcmp(aStr, bStr) compares aStr to bStr. If aStr < bStr, returns a value < 0, returns 0 if aStr == bStr and returns a value > 0 if aStr > bStr
int strncmp(aStr, bStr, n) as above but only compares up to n chars
char *strchr(aStr, bChr) returns pointer to first occurrence of char bChr in string aStr or NULL
char *strrchr(aStr, bChr) returns pointer to last occurrence of char bChr in string aStr or NULL
size_t strspn(aStr, bStr) starting from the first char in aStr, returns the number of chars in aStr that can be found in bStr irrespective of order.
size_t strcspn(aStr, bStr) starting from the first char in aStr, returns the number of chars in aStr that are not found in bStr
char *strpbrk(aStr, bStr) returns a pointer to the first occurrence of any char in bStr in aStr or NULL
char *strstr(aStr, bStr) returns a pointer to the first occurrence of string bStr in aStr or NULL
size_t strlen(aStr) returns the length of aStr excluding the terminating null char
char *strtok(aStr, delimStr) repeated calls return the positions of one or more delimited string found in aStr (see below after math.h)
void *memcpy(aStr, bStr, n) copies n chars from bStr to aStr
void *memmove(aStr, bStr, n) as above but aStr and bStr can overlap in memory
int memcmp(*a, *b, n) compares first n bytes of memory location a with location b with same return values as strcmp()
void *memchr(aStr, bChr, n) returns pointer to first occurrence of char bChr in first n chars of string aStr or NULL
void *memset(aStr, bChr, n) sets first n chars of string aStr to value of char bChr

<stdlib.h>

double atof(aStr) converts string aStr to type double. Ignores leading whitespace, accepts a leading sign (optional) and ignores trailing characters not deemed part of double representation.
int atoi(aStr) As atof but converts string aStr to type int.
long atoll(aStr) As atof, converts string aStr to type long
double strtod(aStr, char **endp) converts numeric characters from the start of aStr to a double. If the char pointer endp is not null then it is set to the address of the first char in aStr that could not be included in the conversion.
long strtol(aStr, char **endp, int base) similar to strtod() but returns a long. In addition, the number base can be set to a value between 2 and 36. If base is 0 then the function expects the string aStr to indicate the base. A leading 0 indicates base 8, 0x hexadecimal with base 10 the default.
unsigned long strtoul(aStr, char **endp, int base) same as strtol but returns an unsigned long
void *malloc(n) returns a pointer to a new memory allocation n bytes long or NULL if no space available
void *calloc(s, n) returns a pointer to a new memory allocation with space for n elements of an array where each element is size s bytes. Returns NULL if requested space is not available
void *realloc(void *p, s) changes an existing memory allocation.
void free(void *p) deallocates memory identified by pointer p that must have been previously allocated by malloc(), calloc() or realloc()
long labs(l) returns absolute value of long l
struct{
int quot;
int rem
} div_t div(int num, int denom)
divides num by denom and returns the struct with the quotient in quot and the remainder in rem
struct{
long quot;
long rem;
} ldiv_t ldiv(long num, long denom)
as div() above but for long integers

The malloc() and free() functions are not, what is called, re-entrant. If they are called directly or indirectly from an interrupt handler (as our Morse FiFo queue did) then they should not also be used concurrently from normal program functions.

<math.h>

Trigonometric function arguments express angles in radians and not degrees. All of the math.h library functions return a value of type double. Other “standard Arduino” math functions are documented in chapter 4 of this book.

asin(r) sine-1 of angle r
acos(r) cosine-1 of angle r
atan(r) tan-1 of angle r
atan2(x / y) tan-1 of x / y
sinh(r) hyperbolic sine of r
cosh(r) hyperbolic cosine of r
tanh(r) hyperbolic tangent of r
exp(x) exponential function ex
log(x) natural logarithm of x
log10(x) base 10 logarithm of x
ceil(x) smallest integer not less than x, returned as double
floor(x) largest integer not greater than x, returned as double. Mind negative values of x
fabs(x) absolute value of x
ldexp(x, n) returns x multiplied by 2 raised to the power n
frexp(x, int *e) computes a fraction multiplied by a power of 2 that is equal to x. returns the fraction and writes the power of 2 to e(xponent)
modf(x, double *i) takes a double x, returns the fractional component while the integer component is stored in i
fmod(x, y) returns the remainder of x after being divided by y

Some of these library functions are easier to describe in a few words than others. I think that strtok() needs a full explanation and a demo program. Many programming languages have something equivalent to a split() function that takes a string and returns an array of strings with each element from the original string delimited by some character. Aspects of that would represent something of a challenge in C but strtok() provides the required functionality in a style consistent with the language.

The function is passed a string to tokenise together with a string containing one or more delimiter. The function finds the first delimiter character in the string and replaces it with a null char. It then returns a pointer to the start of the string before the inserted null char. Subsequent calls to the same function cause the search for a delimiting char to start from the last one found. Each time the function finds a delimiter (or the string terminator) it does the substitution and returns a pointer to the start of the new string segment. Warning: this function makes changes to the original string.

A short demo code snippet should help with the explanation

template<class T> inline Print &operator <<(Print &obj, T arg) { obj.print(arg); return obj; } char test[] = "Strange, that this is a test string"; char delim[] = ", "; // comma and space act as delimiters void setup() { Serial.begin(115200); char *pc = strtok(test, delim); while (pc != NULL) {     Serial << pc << '\n';     pc = strtok(NULL, delim); } Serial << "but now test is: " << test << '\n'; }

With the Serial Monitor showing:

Strange
that
this
is
a
test
string
but now test is: Strange

Notice that the second and subsequent calls to strtok() passes a NULL instead of the string that is being tokenised. This indicates to the function that it should continue with that last string and where it had previously left off.