ADT in C - with or without pointers?
In theory it see开发者_StackOverflow社区ms that books sugest declaring ADT in C as:
struct some_structure;
typedef some_structure *some_structure_t;
while most code uses:
struct some_structure;
typedef some_structure some_structure_t;
I know that const
is not working with the first style. Is this the only reason for real libraries not to use first approach? Any further notices or suggestions?
you mean abstract data type? If I abstract ;-) from the syntax errors in your code snipsets, I think, yes typedef
of pointer types is frowned upon because problems with const
and volatile
.
BTW, another problem with your code are the names you have chosen. _t
as an ending is reserved for future use in POSIX.
An abstract data type is useful as a way of effectively performing actions on something like an "object".
If you can, in C, avoid the "typedef" keyword with structures altogether. It masks what is really happening. As a beginner I recommend you explicitly type struct AStruct
wherever you would be tempted to use a typedef.
From there you perform an "action" on your "abstract data type" by declaring a function that takes a pointer to the "abstract data type" (or object, as I like to think) as the first parameter, and then the normal parameters afterwards.
e.g.
int some_func( struct AStruct *pObject, int param1, int param2 ) {
if ( ( param1 < 0 ) || ( param2 < 0 ) )
return( 0 );
pObject->val = param1 + param2;
return( 1 );
}
Then to use:
#include <stdio.h>
int main( void ) {
struct AStruct myObject;
if ( some_func( &myObject, 10, 12 ) ) {
printf( "Processed: %d\n", myObject.val );
} else {
printf( "Failed\n" );
}
return( 0 );
}
It depends on what other people's code will do with those types. As a user of your library, if I assume that some_structure_t is a struct instead of a pointer to a struct, I might do something like this:
some_structure_t *p;
p = malloc( sizeof *p);
memcpy( p, &another_p, sizeof *p);
Maybe it's my background as an embedded programmer, but I want to know more about some_structure_t
in my code that uses it. Even if it's a truly abstracted type, and it's only used as a parameter or return value in end-user code, you still have to deal with it in the library that supports the type. If I saw the following code, I'd do a double take:
some_structure_t some_function( some_structure_t foo)
{
some_structure_t retval;
retval = malloc( sizeof *retval); // assigning pointer to struct?
retval->member = foo->member; // using -> instead of .?
return retval; // returning potentially large structure on stack?
}
And maybe this is the biggest one -- copying from one some_structure_t
to another. If it's an int
or a float
or a struct
, writing foo = bar
will make a copy. If some_structure_t
is defined as a pointer to a struct, now foo
and bar
point to the same object. Maybe that's what you want, but it seems risky to me.
I wonder if MISRA has anything to say about typedefs that are pointers.
I use
typedef struct some_s *some_t;
and where it matters I either use const struct some_s*
or typedef const struct some_s *const_some_t
, but I guess that's a question of personal taste.
I used to go with the first style, but I found that I tended to get confused about the levels of indirection I needed to access structure members so I started adding suffixes to the pointer type e.g.
typedef struct AStruct *AStructRef;
But then I realised I was effectively reinventing the * operator in order to stop myself from being confused by my attempt to hide the * operator. So now I go with the second style.
精彩评论