better way to check bit in c

MrSoftware

Joined Oct 29, 2013
2,273
typdefs are very useful in some situations. For example, I did a lot of work implementing file systems and it's very nice to have explicit data types that match the different fields in the file system specification. Type checking is a very useful feature of the language.
 

WBahn

Joined Mar 31, 2012
32,973
In what way is that construct "incorrect"? Forward declarations are a natural and useful aspect of the language.

On the other hand, I consider typedefs generally evil. Their greatest effect is to obscure.
So do you believe that typedefs like uint32_t, time_t, and FILE are evil?

EDIT: Fixed typo.
 
Last edited:

bogosort

Joined Sep 24, 2011
696
So do you believe that typedefs like uint32_t, time_t, and FILE are evil?

EDIT: Fixed typo.
As I said, "generally evil" -- not all typedefs are bad. In particular, the width-specifying typedefs (such as uint32_t) are the opposite of obscuring, and so are happily used. Likewise, I'm perfectly happy to use typedefs for an opaque library object, e.g., the FILE struct.

I'm much less enthused about time_t, size_t, and their ilk. And I hate source-level typedefs, e.g., obscuring the type of a local struct or function pointer, etc., whose only purpose seems to be slightly less typing. When I'm going through unfamiliar code, the last thing I want is to have to keep a separate symbol table for an abstraction over the type system on my "stack".
 

WBahn

Joined Mar 31, 2012
32,973
As I said, "generally evil" -- not all typedefs are bad. In particular, the width-specifying typedefs (such as uint32_t) are the opposite of obscuring, and so are happily used. Likewise, I'm perfectly happy to use typedefs for an opaque library object, e.g., the FILE struct.

I'm much less enthused about time_t, size_t, and their ilk. And I hate source-level typedefs, e.g., obscuring the type of a local struct or function pointer, etc., whose only purpose seems to be slightly less typing. When I'm going through unfamiliar code, the last thing I want is to have to keep a separate symbol table for an abstraction over the type system on my "stack".
If you believe that their only purpose is to offer slightly less typing, then you would probably benefit from delving into why typedefs are used and what benefits they offer. There are several layers and it is not uncommon for superficial users to see primarily the typing savings.

The alternative to using something like size_t is having to go through however many thousands of lines of code you have whenever you change compiler version in order to identify which variables now need to be unsigned int instead of unsigned long and all of the other cases -- most of which you will only know as the numerous bugs you've just created by keeping your original variable types when they need to be a different type now rise up and bite you or your customers.

Typedefs also allow the compiler to do much better type checking so that you can at least get warnings when you make many of the common mistakes.
 

bogosort

Joined Sep 24, 2011
696
If you believe that their only purpose is to offer slightly less typing, then you would probably benefit from delving into why typedefs are used and what benefits they offer. There are several layers and it is not uncommon for superficial users to see primarily the typing savings.
I'm far from a "superficial" user of C, but I'm happy to uncover any blind spots I may have.

The alternative to using something like size_t is having to go through however many thousands of lines of code you have whenever you change compiler version in order to identify which variables now need to be unsigned int instead of unsigned long and all of the other cases -- most of which you will only know as the numerous bugs you've just created by keeping your original variable types when they need to be a different type now rise up and bite you or your customers
I'm of the belief that if code is sensitive to integer storage size, then the explicit-width types should be used. This ensures that both the programmer and the compiler are in explicit agreement. For code that is not storage-sensitive -- e.g., the index of a short loop -- I default to the int type, as it's guaranteed to be at least 16-bits, and generally the most efficient size for the architecture. While a smart compiler may optimize the storage of 'i' in "for ( size_t i = 0; i < 100; ++i )" behind the scenes, the busy programmer reading through the code has to pause a beat to consider why size_t was used.

My understanding is that size_t was introduced specifically for functions that accept/return the size of an object, as in malloc(), free(), calloc(), etc., and of course the sizeof operator. As such, size_t is guaranteed to be able to hold the largest possible size of an object in the architecture. So, unless the variable in question represents an actual size of some internal data structure, size_t is a poor choice as a general data type.

Typedefs also allow the compiler to do much better type checking so that you can at least get warnings when you make many of the common mistakes.
Can you give me an example where a typedef shows the compiler doing much better type checking than without?

As I said before, typdefs can be useful in certain circumstances. Opaque library APIs and edge-case portability issues (as in compiling for wildly different archs) come to mind. What am I missing?
 

WBahn

Joined Mar 31, 2012
32,973
I'm far from a "superficial" user of C, but I'm happy to uncover any blind spots I may have.



I'm of the belief that if code is sensitive to integer storage size, then the explicit-width types should be used. This ensures that both the programmer and the compiler are in explicit agreement.
Quite the opposite -- it will virtually guarantee that your code will break down the road.

When I first started programming in C, a pointer was a 16-bit unsigned int on most compilers. On most compilers today it is 32 bits and on an increasing number of compilers it is 64 bits.

If I write code today that explicitly makes pointers a 32-bit unsigned int to match the compiler I am using and then later compile it on a 64-bit compiler, my code is broken. I need to use a data type that guarantees that the type used for the pointers will match the data type used by the compiler. Typedefs make this easy.

My understanding is that size_t was introduced specifically for functions that accept/return the size of an object, as in malloc(), free(), calloc(), etc., and of course the sizeof operator. As such, size_t is guaranteed to be able to hold the largest possible size of an object in the architecture. So, unless the variable in question represents an actual size of some internal data structure, size_t is a poor choice as a general data type.
If someone is using size_t as a general purpose data type, then they are abusing the type system just as much as if they used a FILE structure or a clock_t or anything else for general purpose data storage.
 

bogosort

Joined Sep 24, 2011
696
If I write code today that explicitly makes pointers a 32-bit unsigned int to match the compiler I am using and then later compile it on a 64-bit compiler, my code is broken. I need to use a data type that guarantees that the type used for the pointers will match the data type used by the compiler. Typedefs make this easy.
I don't understand what you mean. When we declare a pointer type, the compiler handles the pointer storage -- we don't have any say whether it's a 32- or 64-bit pointer. If instead you're talking about explicit pointer arithmetic, such as adding and subtracting memory addresses, then I agree that using the typedefs size_t, uintptr_t, ptrdiff_t, etc. can be useful in writing portable code. But I consider programs that use memory addressing as essentially non-portable, needing much more attention and care than simple typedefs can provide.

If someone is using size_t as a general purpose data type, then they are abusing the type system just as much as if they used a FILE structure or a clock_t or anything else for general purpose data storage.
100% agreed, so I must have missed your point about size_t.

I still haven't seen a good reason to use typedef'd structs (other than less typing).
 
Top