Follow Slashdot blog updates by subscribing to our blog RSS feed

 



Forgot your password?
typodupeerror
×
User Journal

Journal ryanr's Journal: I have some stupid C questions 13

OK, so I have some C questions that I don't know the answer to. You didn't think that just because I've been lecturing on bugs that I know what I'm doing, did you? :) I'm hoping someone knows the answers.

Doing structs. I'll have something like the following:

typedef struct _structname
{
    int member1;
    int member2;
} structname;

Now, as I understand it, _structname is a type definition, and structname is an instance. In other words, I can do stuff like:

_structname mystruct;

or

structname.member1 = 10;

Being that you don't always need a type definition or an instance (yet), then you can leave either _structname or structname out (but not both).

No problem, I'm following fine so far. (Assuming I've described it correctly, anyway.)

Now, I want to do a linked list:

typedef struct queuenode *qptr;

typedef struct queuenode
{
    time_t time;
    unsigned long address;
    qptr next;
} Queue;

In the above example, I would want to leave out the instance Queue. I don't have a use for Queue at that level, and I don't like it polluting my global namespace. In my experience, the compiler complains unless I have it in. Can anyone tell me why?

Second question. Is there a way to get back to a "regular" name when passing pointers between functions? This is hard to explain, which is probably part of the reason why I have difficulty searching for the answer on my own. Here's an example:

#include
#include
#include

void myalloc (char **buf);

int main()
{
    char *buf;
    myalloc (&buf);
    printf ("%s\n", buf);
    return 0;
}

void myalloc (char **buf)
{
    *buf = (char *)malloc (100);
      strcpy (*buf, "hello");
}

In the function myalloc, I'd like to refer to *buf by the simple name buf. I.e. I'd rather write:

buf = (char *)malloc (100);
strcpy (buf, "hello");

I have to do *buf, because that's the way it's declared in the function header. I have to declare it that way in the function header, because I have to pass the address of a pointer (as opposed to the value of a pointer) to the function if I need to modify the contents of the pointer.

I *think* the answer is that I have to do it this way. I know, I'm picky, deal. It just gets uglier when you've got structs, and you have to do stuff like *buf->member1 .

Any C wizards got a clue?

This discussion has been archived. No new comments can be posted.

I have some stupid C questions

Comments Filter:
  • Structs:

    No. a typedef declares a new type. The format is:

    typedef [known type] alias ;

    struct _structname
    {
    int member1;
    int member2;
    };

    creates a new struct named _structname. In C (but not C++), if you want to create an instance of it, you would do:

    struct _structname mydata;

    Which creates the variable mydata.

    The typedef lets you type structname mydata; instead. Same result, less typing. C++ automatically does a typedef whenever a struct is created.

    Now, for your linked list example, C doe

    • Thanks for the reply. Yes, I am aware that struct and typedef are seperate concepts, I should have said so. I've just never found a good use for a typedef that wasn't also a struct, so I tend to use them together. I mean, I use uint32 when some library call uses that convention, even though it may map to an unsigned int underneath, and I understand the potential utility of the name staying the same in case you change the type later... I've just never had occasion to alias "int" so far.

      But, it appears th
      • I've just never found a good use for a typedef that wasn't also a struct

        Function pointer types. Especially if you have some really anal prototype checking on your comipler, or are required to produce lint-clean code, typedefs can be a lifesaver.

        Even then there are still recursive defs it can't handle - like a pointer to a funtion that takes a function of its own type as an argument and returns one also of the same type. (can be useful for finite state automoata and the like, depending on how things

        • Aha... you're absolutely correct. I even use it for that frequently, and forgot all about it.

          I do that when I'm manually importing functions from a .dll, for example.
  • For your first question, the answer is that your understanding of structs is slightly off.
    If I declare

    struct _foo
    {
    int bar;
    }baz;

    Then _foo is a type, baz is an instance of _foo, and you can declare instances of _foo as follows:

    struct _foo quux;

    which will declare an object named quux of type foo, and you can do things like

    quux.bar = 42;.
    or
    baz.bar = 42;

    Since that mandatory struct before the declaration is annoying, what you can do is,

    typedef struct foo myfoo;

    and then just declare

    myfoo bl
    • OK, your explanation helps quite a bit, thanks. I gather that I can't have it the way I want. I guess what I would have been after is an anonymous struct definition that I could typedef.

      I'll look into references. I actually compile in C++ mode for no special reason.. but don't really use any C++ features. I find myself wanting a queue/linked list quite often (as hinted at in the example I used) so I may look into that as something I can play with in C++. Seems to me that that might lend itself to the
  • since everyone else has given the run down on structs, their typedefs, and the programmers who love them I won't bother.

    IN terms of the second matter; why not just have a type that is a Pointer pointer?

    typedef char* pPtr;
    pPtr local_buf = NULL;

    then
    local_buf = *buf;

    and play around with local_buf->my_foo
    and the like?

    Thats how I deal with function pointer tables and structs with function pointer members- typedef void (*void_fp)(); or typedef int (*fp)();
    then my_foo.fp( i, j, k);
  • the cleanest way to do this sort of thing is exemplified in the plan 9 [bell-labs.com] coding style, IMHO. given that the "struct" namespace is separate from the "type" namespace, we never use "struct" apart from when we have to.

    typedef struct Queuenode Queuenode;
    struct Queuenode {
    time_t time;
    ulong address;
    Queuenode *next;
    }
    in this way, if we've got several data structures that mutually refer to one another, you can just put all those typedefs at the start and not bother with any other names at all.

    another nice t

    • Ooooh! The typedef and the struct can have the same name? That would be exactly what I want...

      There's a code style I should have used, as evidenced by my disappearing #include statements.

      I haven't touched Plan 9 yet. One of these days.
  • A struct can be completely anonymous, although gcc will flag it as a warning:

    struct {
    int anonymous;
    };

    GCC gives "warning: unnamed struct/union that defines no instances", but it compiles.

    You don't have to give a struct a name, or instantiate it, although one normally does one or the other (or both).

    What this means is that you can take a declaration of an anonymous struct:

    struct {
    int pork;
    char beef;
    };

    ... and wrap it in a typedef:

    typedef struct {
    int pork;
    char beef;
    } meat;

    Since

    • ...although this method will keep you from using the name in a self-referential way. This will fail:

      typedef struct {
      int pork;
      char beef;
      meat *ptr;
      } meat;

      ...because until after the typedef, the type "meat" isn't valid. What you can do, if you need the struct to be self-referential, is give the struct a name as the previous poster, but you can do it all in the same top-level expression:

      typedef struct meat {
      int pork;
      char beef;
      struct meat *ptr;
      } meat;

      This is a little messier, bu

"Gravitation cannot be held responsible for people falling in love." -- Albert Einstein

Working...