3
sign up log in tour help stack overflow careers Take the 2-minute tour × Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free. Void pointers to struct pointers in C I am learning C, mainly by K&R, but now I have found an Object Oriented C pdf tutorial and am fascinated. I'm going through it, but my C skills/knowledge may not be up to the task. This is the tutorial: http://www.planetpdf.com/codecuts/pdfs/ooc.pdf My question comes from looking at many different functions in the first couple of chapters of the pdf. Below is one of them. (page 14 of pdf) void delete(void * self){ const struct Class ** cp = self; if (self&&*cp&&(*cp)->dtor) self = (*cp)->dtor(self); free(self); } dtor is a destructor function pointer. But knowledge of this isn't really necessary for my questions. My first question is, why is **cp constant? Is it necessary or just being thorough so the code writer doesn't do anything damaging by accident? Secondly, why is cp a pointer-to-a-pointer (double asterisk?). The struct class was defined on page 12 of the pdf. I don't understand why it can't be a single pointer, since we are casting the self pointer to a Class pointer, it seems. Thirdly, how is a void pointer being changed to a Class pointer (or pointer-to-a-Class-pointer)? I think this question most shows my lack of understanding of C. What I imagine in my head is a void pointer taking up a set amount of memory, but it must be less than Class pointer, because a Class has a lot of "stuff" in it. I know a void pointer can be "cast" to another type of pointer, but I don't understand how, since there may not be enough memory to perform this. Thanks in advance c pointers struct asked May 3 '12 at 17:54 user485498 3 @Joe Absolutely nothing wrong with that. Good C programming skills are so valuable and hard to find these days of rapid scripties. jman May 3 '12 at 17:57 @Joe - I assume it means ANSI C89, which the newer K&R book discussed. the code in the example isn't K&R C IIRC. Flexo May 3 '12 at 18:00 I am reading K&R ANSI (I think from 1989, as you stated.)The code example comes form the OOC pdf user485498 May 3 '12 at 18:02 3 Answers Interesting pdf. My first question is, why is **cp constant? Is it necessary or just being thorough so the code writer doesn't do anything damaging by accident? It's necessary so the writer doesn't do anything by accident, yes, and to communicate something about the nature of the pointer and its use to the of the code. reader Secondly, why is cp a pointer-to-a-pointer (double asterisk?). The struct class was defined on page 12 of the pdf. I don't understand why it can't be a single pointer, since we are casting the self pointer to a Class pointer, it seems. Take a look at the definition of (pg 13) where the pointer is created (the same pointer that's passed as to ): new() p self delete() void * new (const void * _class, ...)

Void Pointers to Struct Pointers in C - Stack Overflow

Embed Size (px)

DESCRIPTION

Pointers

Citation preview

  • sign up log in tour help stack overflow careers

    Take the 2-minute tour Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free.

    Void pointers to struct pointers in C

    I am learning C, mainly by K&R, but now I have found an Object Oriented C pdf tutorial and am fascinated. I'm going through it, but myC skills/knowledge may not be up to the task. This is the tutorial: http://www.planetpdf.com/codecuts/pdfs/ooc.pdf

    My question comes from looking at many different functions in the first couple of chapters of the pdf. Below is one of them. (page 14 ofpdf)

    void delete(void * self){ const struct Class ** cp = self;

    if (self&&*cp&&(*cp)->dtor) self = (*cp)->dtor(self); free(self);

    }

    dtor is a destructor function pointer. But knowledge of this isn't really necessary for my questions.

    My first question is, why is **cp constant? Is it necessary or just being thorough so the code writer doesn't do anything damagingby accident?

    Secondly, why is cp a pointer-to-a-pointer (double asterisk?). The struct class was defined on page 12 of the pdf. I don'tunderstand why it can't be a single pointer, since we are casting the self pointer to a Class pointer, it seems.

    Thirdly, how is a void pointer being changed to a Class pointer (or pointer-to-a-Class-pointer)? I think this question most shows mylack of understanding of C. What I imagine in my head is a void pointer taking up a set amount of memory, but it must be less thanClass pointer, because aClass has a lot of "stuff" in it. I know a void pointer can be "cast" to another type of pointer, but I don'tunderstand how, since there may not be enough memory to perform this.

    Thanks in advance

    c pointers struct

    asked May 3 '12 at 17:54user485498

    3

    @Joe Absolutely nothing wrong with that. Good C programming skills are so valuable and hard to find thesedays of rapid scripties. jman May 3 '12 at 17:57

    @Joe - I assume it means ANSI C89, which the newer K&R book discussed. the code in the example isn'tK&R C IIRC. Flexo May 3 '12 at 18:00

    I am reading K&R ANSI (I think from 1989, as you stated.)The code example comes form the OOC pdfuser485498 May 3 '12 at 18:02

    3 Answers

    Interesting pdf.

    My first question is, why is **cp constant? Is it necessary or just being thorough so the codewriter doesn't do anything damaging by accident?

    It's necessary so the writer doesn't do anything by accident, yes, and to communicatesomething about the nature of the pointer and its use to the of the code.reader

    Secondly, why is cp a pointer-to-a-pointer (double asterisk?). The struct class was definedon page 12 of the pdf. I don't understand why it can't be a single pointer, since we arecasting the self pointer to a Class pointer, it seems.

    Take a look at the definition of (pg 13) where the pointer is created (the samepointer that's passed as to ):

    new() p

    self delete()

    void * new (const void * _class, ...)

  • { const struct Class * class = _class; void * p = calloc(1, class > size); * (const struct Class **) p = class;

    So, 'p' is allocated space, then dereferenced and assigned a pointer value (the address inclass; this is like dereferencing and assigning to an int pointer, but instead of an int, we'reassigning an address). However, p was allocated space for more than just that (it will also hold the object's instancedata). Now consider again:

    This means the first thing in p is a pointer to its class definition.

    delete()

    const struct Class ** cp = self; if (self&&*cp&&(*cp)->dtor)

    When cp is dereferenced, since it was a pointer to a pointer, it's now a pointer. What does apointer contain? An address. What address? that's at thebeginning of the block pointed to by p.

    The pointer to the class definition

    This is sort of clever, because p's not really a pointer to a pointer -- it has a larger chunk ofmemory allocated which contains the specific object data. However, at the very beginning ofthat block is an address (the address of the class definition), so if p is dereferenced into apointer (via casting or cp), you have access to that definition. So, the class definition existsonly in one place, but each instance of that class contains a reference to the definition. Makesense? It would be clearer if p were typed as a struct like this:

    struct object { struct class *class; [...]};

    Then you could just use something like instead of the existing code in . However, this would mess up and complicate the larger picture.

    p->class->dtor()

    delete()

    Thirdly, how is a void pointer being changed to a Class pointer (or pointer-to-a-Class-pointer)? I think this question most shows my lack of understanding of C. What I imagine inmy head is a void pointer taking up a set amount of memory, but it must be less than Classpointer, because aClass has a lot of "stuff" in it.

    A pointer is like an int -- it has a small, set size for holding a value. That value is a memoryaddress. When you dereference a pointer (via or ) what you are accessing is thememory at that address. But since memory addresses are all the same length (eg, 8 bytes ona 64-bit system) pointers themselves are all the same size regardless of type. This is how themagic of the object pointer 'p' worked. To re-iterate: the first thing in the block of memory points to is an address, which allows it to function as a pointer to a pointer, and when that isdereferenced, you get the block of memory containing the class definition, which is separatefrom the instance data in .

    * ->

    p

    p

    edited May 3 '12 at 18:52 answered May 3 '12 at 18:33delicateLatticeworkFever6,845 10 36

    1. In this case, that's just a precaution. The function shouldn't be modifying the class (in fact,nothing should probably), so casting to makes sure that the classis more difficult to inadvertently change.

    const struct Class *

    2. I'm not super-familiar with the Object-Oriented C library being used here, but I suspect thisis a nasty trick. The first pointer in is probably a reference to the class, sodereferencing will give a pointer to the class. In effect, can always be treatedas a .

    self

    self self

    struct Class **

    A diagram may help here:

    +--------+self -> | *class | -> [Class] | .... | | .... | +--------+

    3. Remember that all pointers are just addresses.* The type of a pointer has no bearing onthe size of the pointer; they're all 32 or 64 bits wide, depending on your system, so youcan convert from one type to another at any time. The compiler will warn you if you try toconvert between types of pointer without a cast, but pointers can always beconverted to anything without a cast, as they're used throughout C to indicate a "generic"

    void *

  • pointer.

    *: There are some odd platforms where this isn't true, and different types of pointers are in factsometimes different sizes. If you're using one of them, though, you'd know about it. In allprobability, you aren't.

    answered May 3 '12 at 18:22duskwuff86.3k 11 87 128

    1. is used to cause a compilation error if the code attempts to change anything withinthe object pointed to. This is a safety feature when the programmer intends only to readthe object and does not intend to change it.

    const

    2. is used because that must be what was passed to the function. It would be a graveprogramming error to re-declare it as something it is not.**

    3. A pointer is simply an address. On almost all modern CPUs, all addresses are the samesize (32 bit or 64 bit). Changing a pointer from one type to another doesn't actually changethe value. It says to regard what is at that address as a different layout of data.

    answered May 3 '12 at 18:19wallyk37.2k 7 39 85