I have the below C++ code which issues a compilation warning as shown below.
Case 1:
char temp_buffer[80];
double **data;
....
sprintf(temp_buffer, "%.*g", sizeof(temp_buffer), **data);
Compilation warning:
extension.C:1031:41: warning: field precision specifier '.*' expects argument of type 'int', but argument 3 has type 'long unsigned int' [-Wformat=]
1031 | sprintf(temp_buffer, "%.*g", sizeof(temp_buffer), **data);
| ~~^~ ~~~~~~~~~~~~~~~~~~~
| | |
| int long unsigned int
I am fixing the warning by type-casting the sizeof to int like below.
Case 2:
char temp_buffer[80];
double **data;
...
sprintf(temp_buffer, "%.*g", (int)sizeof(temp_buffer), **data);
But now I get the below warning:
extension/extension.C:1031:39: warning: \u2018%.*g\u2019 directive writing between 1 and 87 bytes into a region of size 80 [-Wformat-overflow=]
1031 | sprintf(temp_buffer, "%.*g", (int)sizeof(temp_buffer), **data);
| ^~~~
extension/extension.C:1031:38: note: assuming directive output of 86 bytes
1031 | sprintf(temp_buffer, "%.*g", (int)sizeof(temp_buffer), **data);
| ^~~~~~
In file included from /usr/include/stdio.h:873,
from /opt/python/python-3.9/include/python3.9/Python.h:25,
from /codemill/dhamodha/projects/base/src/lib/despython/desnumpyinit.h:19,
from extension/extension.C:8:
/usr/include/bits/stdio2.h:36:34: note: \u2018__builtin___sprintf_chk\u2019 output between 2 and 88 bytes into a destination of size 80
36 | return __builtin___sprintf_chk (__s, __USE_FORTIFY_LEVEL - 1,
| ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
37 | __bos (__s), __fmt, __va_arg_pack ());
I was under the assumption that '*' in the precision internally coerces the long unsigned int to int. But had that been the case the new warning wouldn't happen if I introduce sizeof typecasting.
Can someone help me in understand what's going on and solve the warnings?
Case 3:
Say I modify the temp_buffer to size 8, then I see both warnings:
extension/extension.C:1033:20: warning: \u2018%.*g\u2019 directive writing between 1 and 310 bytes into a region of size 8 [-Wformat-overflow=]
1033 | sprintf(temp_b, "%.*g", sizeof(temp_buffer), **data);
| ^~~~
extension/extension.C:1033:19: note: assuming directive output of 12 bytes
1033 | sprintf(temp_b, "%.*g", sizeof(temp_buffer), **data);
| ^~~~~~
In file included from /usr/include/stdio.h:873,
from /opt/python/python-3.9/include/python3.9/Python.h:25,
from /codemill/dhamodha/projects/base/src/lib/despython/desnumpyinit.h:19,
from extension/extension.C:8:
/usr/include/bits/stdio2.h:36:34: note: \u2018__builtin___sprintf_chk\u2019 output between 2 and 311 bytes into a destination of size 8
36 | return __builtin___sprintf_chk (__s, __USE_FORTIFY_LEVEL - 1,
| ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
37 | __bos (__s), __fmt, __va_arg_pack ());
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~