2024-03-10 12:18 AM - edited 2024-03-10 01:20 AM
Dear @Khouloud ZEMMELI , @Imen.D , @Pavel A. ,
Please connect me to someone who can help resolve issue with format specifiers mentioned in inttypes.h
I am building code for STM32H7xx microcontroller.
Concern 1:
Is it possible to update inttypes.h, as I believe PRIu32 should:
#define PRIu32 "u"
and not what is being defined/declared in inttypes.h file.
I believe the return type for sizeof() (used by STM32CubeIDE) is unsigned int, but the STM32CubeIDE is reporting warning (when I am trying to find the size of RECTANGLE array:
warning: format '%lu' expects argument of type 'long unsigned int', but argument 3 has type 'unsigned int' [-Wformat=]
39 | sprintf(tmpstr, "sizeof(RECTANGLE) %" PRIu32 "\n", sizeof(RECTANGLE));
| ^~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
| |
| unsigned int
Concern 2:
"display" is an array that exists in external RAM
warning: format '%u' expects argument of type 'unsigned int', but argument 3 has type 'DISPLAY *' [-Wformat=]
45 | sprintf(tmpstr, "addr(display) %" PRIuPTR "\n", &display);
| ^~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~
| |
| DISPLAY *
Also,
warning: format '%p' expects argument of type 'void *', but argument 3 has type 'DISPLAY *' [-Wformat=]
45 | sprintf(tmpstr, "addr(display) %p\n", &display);
| ~^ ~~~~~~~~
| | |
| | DISPLAY *
| void *
Concern 3:
For 32 bit microcontroller, if possible please define uint32_t as "unsigned int" and NOT as "unsigned long"
2024-03-10 01:01 AM
Forget your beliefs, check the C standard. The return type of sizeof is - surprise - size_t. For printing size_t, format specifier %zu should be used.
For portability reasons, uint32_t on 32-bit ARM is defined as unsigned long. In practice this is a source of many problems.
2024-03-10 01:09 AM
The STM32CubeIDE reports return type of sizeof as unsigned int.
2024-03-10 01:23 AM - edited 2024-03-10 01:24 AM
Whether the below line of code work without issues when porting code to different (bit) size microcontroller or when using a different compiler?
sprintf(tmpstr, "addr(display) %" PRIuPTR "\n", (ptrdiff_t)(&display));
2024-03-10 03:01 AM
Check the C standard again. %t is a specifier for ptrdiff_t but if you want to print pointer, not ptrdiff_t, so use %p or whatever suits you, without conversion to ptrdiff_t.
2024-03-10 03:09 AM - edited 2024-03-10 03:21 AM
(for 32 bit microcontroller)
Also inside stddef.h (present with STM32CubeIDE):
#ifndef __PTRDIFF_TYPE__
#define __PTRDIFF_TYPE__ long int
#endif
typedef __PTRDIFF_TYPE__ ptrdiff_t;
and in inttypes.h (present with STM32CubeIDE):
/* 32-bit types */
#define __PRI32(x) __INT32 __STRINGIFY(x)
#define __SCN32(x) __INT32 __STRINGIFY(x)
#define __PRI32LEAST(x) __LEAST32 __STRINGIFY(x)
#define __SCN32LEAST(x) __LEAST32 __STRINGIFY(x)
#define __PRI32FAST(x) __FAST32 __STRINGIFY(x)
#define __SCN32FAST(x) __FAST32 __STRINGIFY(x)
#define PRId32 __PRI32(d)
#define PRIi32 __PRI32(i)
#define PRIo32 __PRI32(o)
#define PRIu32 __PRI32(u)
#define PRIx32 __PRI32(x)
#define PRIX32 __PRI32(X)
2024-03-10 06:32 AM - edited 2024-03-10 06:48 AM
@RajeevAroraCrcEvans Unfortunately change of inttypes.h won't help because the checking logic is in the compiler.
On 32-bit Arm Cortex, int, long and pointer types all are 32 bit. But the compiler (abiding by the standard) distinguishes int and long types. Type int32_t is defined as long from "historical reasons". So formally (u)int32_t values require prefix "l" in format spec. This is very annoying. Same with size_t and ptrdiff_t. They are mapped to long in the compiler, though actually they are 32-bit same as plain int. As @gbm answered, the type of sizeof value by definition is size_t.
With C++ streams you won't have this annoyance because the << operator has all needed overload forms.
/* If it can relieve you, I hate these PRIx things and instead typecast the printf arguments to (int) or (unsigned) where it makes sense. Or use one of alternative replacements of printf and thus avoid the parameter checking by the compiler */
Change of the types mapping in the C compiler (and its stdint & inttypes.h) is possible, if you build your own target compiler, such as with yocto. If done in a public release, this will break a lot of existing code and disturb a lot of users.