1
\$\begingroup\$

So I got this code up and running and it works fine but I don't understand just why and what it is the code concerning the ldc display string is doing. I know it has something to do with different type of microcontrollers and the string needs to be converted to like an unsigned 8 bit integer in this case to work? Below is the code.this is on a L476VG Discovery Board with an STM32L476 arm microcontroller enter image description here

\$\endgroup\$
2
\$\begingroup\$

In C language, string literals like "HELLO" are of type const char*, i.e. it's a pointer to a constant signed 1-byte type. The cast changes it to a pointer to non-constant unsigned 1-byte type. They are 100% identical on the hardware level and some older C language compilers didn't care much about it as well, especially the const part, but modern C language requires this explicit cast if the function is defined with parameter of type uint8_t*. The compiled code contains effectively no code to do the cast, it is a "zero-price operation", it is just something syntactically needed in C langauge.

\$\endgroup\$
  • 1
    \$\begingroup\$ Pedantically, string literals in C are of type char[] (unlike C++ where they are const char[]). Also, char is not necessarily a signed type. \$\endgroup\$ – Lundin Feb 5 at 10:23
  • \$\begingroup\$ Also a bit pedantic, but is there any situation where the compiler would have to insert code to perform a C pointer cast? I can't think of any off the top of my head. \$\endgroup\$ – Jon Feb 5 at 11:14
  • \$\begingroup\$ @Jon on architectures where all kind of pointers have the same representation (which is probably 99% of processors sold today), casting between pointer types effectively produces no code with plain C. Casting between value types (e.g int/float) may produce code, however. Also in C++, casting pointers may produce some code (e.g. adjusting object base pointer in case of multiple inheritance). \$\endgroup\$ – dim Feb 5 at 13:19
0
\$\begingroup\$

GCC (the compiler st uses) defines char as signed. The function parameter expects an unsigned char. The typecast stops any warnings associated with this difference in signedness.

\$\endgroup\$
-1
\$\begingroup\$

Short answer:

Because your function expects a pointer to an array of uint8_t. A pointer to an array of char, such as your string literal, is not necessarily compatible.

It has nothing to do with "different type of microcontrollers".

Long answer:

For various old and rotten reasons, the type char has implementation-defined signedness in C. Meaning that the compiler decides if it is signed or unsigned in one particular case. But also meaning that char is a distinct type, different from signed char and unsigned char both.

This is why char is completely unsuitable for anything else but the purpose of holding strings. In particular, it should never be used to hold raw binary data or be used for any form of binary of arithmetic. To avoid such signedness pitfalls, hardware-related code that is likely to deal with raw binary data, sometimes uses uint8_t even for holding strings. This is not because hardware-related programming is some special dialect of C - it is simply because such applications are far more likely to expose bugs related to char than hosted system programs are.

For various old and rotten reasons, the type of a string literal ("HELLO") is of type char[] in C. You aren't allowed to write to them, but their type is still not const-qualified. (In C++, they fixed this language bug and string literals are const char[] there.)

You have some manner of API on top of code that is sending raw bytes over a serial bus like SPI or UART. Since it doesn't make any sense for SPI etc to use char, the API will be designed to use uint8_t* (or if properly written with const correctness, const uint8_t*). In case you are sending strings, you have to handle the type conversion in advance.

Luckily, wild pointer casts between char/unsigned char/uint8_t are perfectly safe to use. On systems where uint8_t exists, it is always safe to assume that char will be 8 bits. On exotic legacy systems such as various oddball DSPs, char may have a different number of bits, but then uint8_t won't be available either.

\$\endgroup\$
-2
\$\begingroup\$

It's a cast to pointer to unsigned char. uint8_t is equivalent to unsigned char. Whatever library you are using passes out a byte at a time to the display. You are giving it a pointer to the start of the string, which is just an array.

There is a discussion on uint8_t vs. unsigned char here. Generally speaking, it is good practice to use (unsigned) char for characters, as it documenting your intent.

\$\endgroup\$
  • \$\begingroup\$ I am afraid your stackoverflow link is a completely unrelated discussion on two names of the same unsigned char datatype. \$\endgroup\$ – Al Kepp Feb 4 at 21:52
  • \$\begingroup\$ @AlKepp How so? It's exactly the situation that the OP is asking about. The OP could replace uint8_t with char in their code and it would run, they just seem to confused by the fact it's ostensibly changing a character to a unsigned integer. \$\endgroup\$ – awjlogan Feb 4 at 21:55
  • \$\begingroup\$ No mate, because uint8_t = unsigned char as they are just two names of the very same 1-byte unsigned datatype. The regular char is a different datatype, it is not unsigned. \$\endgroup\$ – Al Kepp Feb 4 at 22:04
  • \$\begingroup\$ @AlKepp Ah, right, yes, I see what you're saying. Edited. \$\endgroup\$ – awjlogan Feb 4 at 22:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.