C++ and MATLAB Simulink tips for HWIL simulation software engineers
Wednesday, September 29, 2021
Safety-Critical System Development
Monday, September 27, 2021
Binary string permutations
Previously, I had solved printing all permutations of a string. As part of a programming contest, I solved binary string permutations using C++. What is interesting in this solution is that is uses a simple for loop and obtains each binary permutation by converting a decimal number to a binary number:
Sunday, September 12, 2021
Hiding internal details of a C++ library
When you need to provide your simulation as an external library (dll, lib) to someone, you should simplify the API as much as possible so that you are able to provide the minimal amount of header files, without exposing details the user doesn't care about. You can achieve this by hiding all the internal dependencies in the implementation (cpp) file. If the user has to be able to create multiple (concurrent) simulations, you can use a static map to hold each simulation object. Here is an example (C++11):
Wednesday, July 14, 2021
C++: Using 1 byte enum
By default, enum size in C++ is usually 4 bytes, both in Windows and Linux. If you need to use 1 byte enum, you have to declare it as follows (requires at least C++ 11):
enum e : unsigned char { a, b };
printf("size = %ld\n", sizeof(e)) will output 1.
If you are using gcc (e.g. Eclipse), you can also use the compiler flag -fshort-enum (Eclipse properties - C/C++ Build - Settings - Tool Settings - GCC C++ Compiler - Miscellaneous) to convert all enums in code to 1 byte, but you won't have that option in Visual Studio. So it is better to use the unsigned char option.
Friday, July 9, 2021
Use memset only with zero
Consider the following C++ definitions:
typedef struct {
int i;
double d[3];
} A_STRUCT
A_STRUCT s;
When I use memset(&s, 0, sizeof(s)), i and d values are set to zero as expected. When I use memset(&s, -1, sizeof(s)), I would expect all values to be -1 but on inspection you will see that they have strange values, in my case i was -1 but d values were -nan. When I use memset(&s, 1, sizeof(s)), I get 16843009 for i and 7.74...e-304 for d values.
Reason: The memset() function writes bytes, not words. So writing 1 to sizeof(int)*100 bytes writes 00000001 to every set of 8-bits.Thus, each integer in binary looks like the following:
0000 0001 0000 0001 0000 0001 0000 0001 (1 int = 4 bytes)
which in decimal is, exactly, 16843009..
memset doesn't only work with 0. It also works with all numbers with identically repeating byte pattern. Like for example ~0.
Tuesday, January 12, 2021
#define considered harmful
In C++, #define has global scope. If you have a #define FAIL (-1) in a header file that you include, you cannot declare a variable named FAIL anywhere else, not even inside a namespace. If you do, you will get the cryptic error message "expected an identifier":
So, don't use define for named constants in C++, use const int etc. If you are using C instead of C++, read this.Friday, December 18, 2020
Software inertia
Imagine software as a snow ball that you want to move forward. As uncle Bob said, if you don't put aside time to clean software, in time its inertia will increase. In the beginning the ball will be light and you will add features, i.e. move the ball easily. With time the code will become messier and changes that took 1 day in the beginning start to take first a couple of days and later weeks. The snow ball gets heavier whenever you move it further. In other engineering disciplines, the more you work on a product, the better it gets, at least it doesn't get much worse. Good luck to software project managers who try to estimate when the project will be done, because the further down the road, the less reliable the estimates are. For any non-trivial project, you can only come up with reasonable time estimates if the code is continuously cleaned up.
