These posts document some of the C concepts that I often forget or confound and some idioms that I’ve encountered. It is intended as a quick reference (for myself). Most of it is not original work, some relevant sources can be found in the inline references, others might be burried in my subconscious.
Arrays
Whenever an array name appears in an expression except as the operand of unary & or the sizeof operator, the value of the array name becomes a pointer to the first element of the array.
1 2 3 4 5 6 |
|
Arrays as function parameters
You can declare functions with array parameters, this is exactly equivalent to using the more common pointer syntax. The type qualifiers following the [ act as if they followed the * when the parameter’s type is rewritten as a pointer type. You can also use the static keyword within the [] to specify a minimum size for the caller passed array pointer. Thus:
1 2 3 |
|
Multidimensional arrays (Variable Length)
In C90 multidimensional arrays can be used with the convinent [i][j][k]
indexing syntax only if the total size of N-1 dimensions (bounds a.k.a stride) are known at compile time. You don’t need to know the size of the last dimension as the stride of this dimension is equal to the sizeof(array_element_type)
. C99 created VLAs to overcome this restriction. Arrays whose size is determined at runtime are called Variable Length Arrays (VLA).
1 2 3 4 5 6 7 8 9 10 11 12 |
|
References:
Randy Meyers has a series of informative articles in the now defunct C/C++ Users Journal that discuss VLAs and other topics summarized on this page in more detail. The journal arcives are available here. Dr.Dobb’s journal (also defunct) has copies of the articles too. VLA Part 1 VLA Part 2 VLA Part 3 VLA Part 4
C99 C99 Rationale C11 Final Draft
Strings
String literals v/s arrays
A string in C is simply an array of chars terminated by a '\0'
. Initialized strings can be created in two ways - one is to statially allocate them in memory and hold a pointer to address where the string is stored, and the other is to store the string as an array of chars. In the first case they are constant and it’s undefined behavior to modify them, while in the second case their contents can be modified [C99 N1256 draft 6.7.8/32 “Initialization”].
1 2 3 |
|
Anonymous string literals can also be used as in printf("Another literal")
, in this case the pointer to the literal is implicitly passed to printf()
on the stack. This by default allocation of debugging strings into data memory eat up a lot of useful RAM. Some targets have a way to relocate strings into program memory, for example AVR has the PROGMEM
keyword which the Arduino platform extended to the F(x)
macro.
Another trick is to use the C99 compound literal sytax to convert the string literal into a char array and push it onto the stack. However this trick only works for short length string literals, larger literals are stored in the data segment and then coped onto the stack at runtime by your smart ass compiler. The boundary was 18 bytes on an embedded MCU I tested with.
1 2 3 4 5 6 7 8 9 |
|
Jagged char arrays
C does not natively support jagged arrays but you can declare an array of variable length strings like:
1 2 |
|
How does it work? Relook at the declreation of pChar2D
- it is an array of pointers to char, which means that when you say pChar2D[0]
you end up getting the address of the string literal "A long long long string"
. Not surprisingly, this is exactly how jagged arrays of other types are programatically dealt with usually. i.e.
1 2 3 4 |
|
If you are unsure about a C declerations, they can be looked up at cdecl.org
Designated Initializers
Initializing individual elements with arrays and structs can be done with designated initializers. Elements that are not specifically initialized are automatically initialized to 0. This is clearly better than the old method of having to initialize members individually which lends garbage values to uninitialized elements. More details here
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Compound literals
Just like how like languages like C# allow you to create and manipulate anonymous objects, C99 allows you to do the same thing with C types like int, struct, union, array etc. These are called compound literals. You are allowed to take the address of these constants and pass them around as function parameters. The basic syntax is (<type>){<initializer-list-expression>}
.
1 2 3 4 |
|