Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best Practices: Should I create a typedef for byte in C or C++?

Do you prefer to see something like t_byte* (with typedef unsigned char t_byte) or unsigned char* in code?

I'm leaning towards t_byte in my own libraries, but have never worked on a large project where this approach was taken, and am wondering about pitfalls.

like image 745
Dan O Avatar asked Sep 11 '09 06:09

Dan O


People also ask

When should I use typedef?

The typedef keyword allows the programmer to create new names for types such as int or, more commonly in C++, templated types--it literally stands for "type definition". Typedefs can be used both to provide more clarity to your code and to make it easier to make changes to the underlying data types that you use.

Is it good to use typedef?

It can almost be necessary when dealing with templates that require multiple and/or variable parameters. The typedef helps keep the naming straight. Not so in the C programming language. The use of typedef most often serves no purpose but to obfuscate the data structure usage.

Why do we use typedef in C?

typedef is a reserved keyword in the programming languages C and C++. It is used to create an additional name (alias) for another data type, but does not create a new type, except in the obscure case of a qualified typedef of an array type where the typedef qualifiers are transferred to the array element type.

What happens internally when we create typedef in C?

Internally there will happen nothing because it is only the information for the compiler that you introduced some alias for another type. ... A typedef declaration does not introduce a new type, only a synonym for the type so specified.


3 Answers

If you're using C99 or newer, you should use stdint.h for this. uint8_t, in this case.

C++ didn't get this header until C++11, calling it cstdint. Old versions of Visual C++ didn't let you use C99's stdint.h in C++ code, but pretty much every other C++98 compiler did, so you may have that option even when using old compilers.

As with so many other things, Boost papers over this difference in boost/integer.hpp, providing things like uint8_t if your compiler's standard C++ library doesn't.

like image 138
Warren Young Avatar answered Sep 21 '22 22:09

Warren Young


I suggest that if your compiler supports it use the C99 <stdint.h> header types such as uint8_t and int8_t.

If your compiler does not support it, create one. Here's an example for VC++, older versions of which do not have stdint.h. GCC does support stdint.h, and indeed most of C99

One problem with your suggestion is that the sign of char is implementation defined, so if you do create a type alias. you should at least be explicit about the sign. There is some merit in the idea since in C# for example a char is 16bit. But it has a byte type as well.


Additional note...

There was no problem with your suggestion, you did in fact specify unsigned.

I would also suggest that plain char is used if the data is in fact character data, i.e. is a representation of plain text such as you might display on a console. This will present fewer type agreement problems when using standard and third-party libraries. If on the other hand the data represents a non-character entity such as a bitmap, or if it is numeric 'small integer' data upon which you might perform arithmetic manipulation, or data that you will perform logical operations on, then one of the stdint.h types (or even a type defined from one of them) should be used.

I recently got caught out on a TI C54xx compiler where char is in fact 16bit, so that is why using stdint.h where possible, even if you use it to then define a byte type is preferable to assuming that unsigned char is a suitable alias.

like image 30
Clifford Avatar answered Sep 21 '22 22:09

Clifford


I prefer for types to convey the meaning of the values stored in it. If I need a type describing a byte as it is on my machine, I very much prefer byte_t over unsigned char, which could mean just about anything. (I have been working in a code base that used either signed char or unsigned char to store UTF-8 strings.) The same goes for uint8_t. It could just be used as that: an 8bit unsigned integer.

With byte_t (as with any other aptly named type), there rarely ever is a need to look up what it is defined to (and if so, a good editor will take 3secs to look it up for you; maybe 10secs, if the code base is huge), and just by looking at it it's clear what's stored in objects of that type.

like image 33
sbi Avatar answered Sep 18 '22 22:09

sbi