Question

In theory it seems 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?

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top