Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C: make a type incompatible with any other types

Is there in C, or at least in GCC, some way of making (with typedef) a type that is incompatible with any other type?

For example, you make:

typedef UINT UID;
typedef UINT AGE;

UID user_id;
AGE user_age;

You can see that both types are unsigned int (I name it UINT).

You can calculate user_id + user_age.

BUT, you want to be sure UIDs and AGEs will never be mixed.

That's what I want!

The idea is for the security and correctness of the code, to specify some qualifier/attribute for some types.

Than, the ONLY way to mix them will be casting both to UINT, or casting user_age to UID, for example.

C language can be very confuse, and sometimes we take HOURS just to find out that silly bug is there just because you used the wrong value as an argument because the variables have similar names... and the compiler obviously will never complain, because they have the same type.

I didn't find any atttribute for this in the GCC manual, but I'm going to request it in the mailing list.

I just want to know HOW (and I know there isn't, the real question I have is WHY the standard and the compiler doesn't provide this, as I see it as really useful and relatively one of the most easy things to implement at the compiler side) to specify some ATTRIBUTE on a type (and also on variables) to tell the compiler that TYPE is not supposed to be mixed with any other, unless explicitly casted to it. So the real question here is: - Why is this a bad idea? (Why no compiler consider it?) - Would you also use it if this GCC attribute existed? Oh... in my opinion I would use it here and there, just put this attribute in almost all typedefs and then just program; a HUGE part of the mistakes would be detected at the first compilation - passing arguments in the wrong order, using the wrong variable in a big and complicated calculation...

Sorry for my bad english.

like image 370
user3525723 Avatar asked Sep 15 '14 16:09

user3525723


2 Answers

Assuming that UINT is defined as some type you can create typedefs for them to make them incompatible. The code below gives an idea how you initialize and manipulate them.

typedef struct { UINT id; } UID;
typedef struct { UINT age; } AGE;

UID user_id = { 1234 }; /* Example of initialization of a struct */
AGE user_age = { 23 };

int main()
{
    UINT add;
    user_age.age = 25; /* example of assignment */
    add = user_id + user_age; /* Example of compile error */

    return 0;
}

There are some downsides as well. You can't use structs with operators (+,-,/,* etc). ie. You can't add two structs together. Because of that this wouldn't work:

AGE user1age = { 25 };
AGE user2age = { 23 };
UINT totage = user1age + user2age;

You'd have to do it this way and explicitly add the age values in the structs:

AGE user1age = { 25 };
AGE user2age = { 23 };
UINT totage = user1age.age + user2age.age;
like image 139
Michael Petch Avatar answered Nov 11 '22 22:11

Michael Petch


Use structs:

typedef struct 
{
  unsigned int uid;
} UID;

typedef struct
{ 
  unsigned int age;
} AGE;

UID user_id;
AGE user_age;
like image 4
alk Avatar answered Nov 11 '22 22:11

alk