I've just started using ncurses
. An array validity
defined as
static const char* validity[] = {
"invalid",
"valid"
};
allows me to map the 0
to invalid
and the 1
to valid
where necessary in order to make a more readable output in my application.
I also have the following lines in my code:
if(data->pos != NULL) {
mvprintw(4, 0,
"Position: X %5d Y %5d Z %5d \n",
data->pos->x, data->pos->y, data->pos->z);
// ...
}
This allows me to output a 3D coordinate that is stored inside a struct data
, which is updated multiple times every second and filled with new coordinates. It works without any issues.
Next thing I have is use mvprintw(...)
to output a single string argument:
if(data->detected != NULL) {
mvprintw(5, 0,
"Detected: %s\n",
booleans[data->detected]);
}
where booleans
is very similar to the validity
array but with true
and false
strings inside to map boolean values to strings. This works too!
However the following code outputs a strange result:
if(data->validity_check != NULL) {
mvprintw(11, 0,
"Validity: %d [%s]\n",
data->validity_check->timestamp,
validity[data->validity_check->valid]);
}
validity_check
is just another struct
that contains a timestamp
(as long integer) and a valid
flag which can be either 0
or 1
.
The output should look for example like
Validity: 123456789 [invalid]
but instead I get
Validity: 123456789 [(null)]
I was quite surprised by this and made an output using printf()
to see if valid
actually contained valid data or not (that's the problem with C-arrays - no check for out of bounds). The result: it did. The values were jumping between 0
and 1
as expected. For some reason however the second argument appeared to be "broken". I even removed the retrieval from the array and used a hard-coded argument value but still no change.
Further investigation made me rewrite this part of the code like this:
if(data->validity_check != NULL) {
mvprintw(11, 0,
"Validity: %d",
data->validity_check->timestamp);
printw(" [%s]\n", validity[data->validity_check->valid]);
}
It worked without any issues and I got the desired result. However I have no idea what I'm doing wrong here. I have looked the documentation multiple times but I'm probably missing something since I can't find anything that can explain this behaviour.
You write:
validity_check
is just anotherstruct
that contains atimestamp
(as long integer) and avalid
flag which can be either0
or1
.
If timestamp
is a long int
, you should use the %ld
format instead of just %d
:
if (data->validity_check != NULL) {
mvprintw(11, 0,
"Validity: %ld [%s]\n",
data->validity_check->timestamp,
validity[data->validity_check->valid]);
}
The printf
family of functions are variadicfunctions and the format string must tell them exactly which type to use. (This is diffferent to normal functions, where the type of arguments is known and types get narrows or promoted as appropriate.)
That's a common type of error, but enabling warnings should tell you about such format mismatches, at least in GCC and Clang.