const struct members

Discussion in 'C Programming' started by Bill Pursell, May 1, 2006.

  1. Bill Pursell

    Bill Pursell Guest

    Suppose I have a structure with many members, and I pass a pointer to
    that structure to a function. I'd like the prototype of the function
    to specify that it will only be changing certain members of the
    function, but I have only the following horrific way to do that. Can
    someone please suggest a better alternative?

    #include <stdio.h>

    struct foo {
    char *a;
    char *b;
    };

    struct const_foo {
    const char *a;
    const char *b;
    };

    struct foo_const_a {
    const char *a;
    char *b;
    };

    struct foo_const_b {
    char *a;
    const char *b;
    };

    void modify_a(struct foo_const_b *f)
    {
    f->a = "a has been changed!";
    }

    void modify_b(struct foo_const_a *f)
    {
    f->b = "b has been changed!";
    }

    void print_foo(struct const_foo *f)
    {
    printf("f.a = %s\nf.b = %s\n", f->a, f->b);
    }

    int main(void)
    {
    struct foo F = {"a string", "b string"};

    print_foo((struct const_foo*)&F);
    modify_a((struct foo_const_b*)&F);
    modify_b((struct foo_const_a*)&F);
    print_foo((struct const_foo*)&F);

    return 0;
    }
     
    Bill Pursell, May 1, 2006
    #1
    1. Advertising

  2. "Bill Pursell" <> wrote in message
    news:...
    > Suppose I have a structure with many members, and I pass a pointer to
    > that structure to a function. I'd like the prototype of the function
    > to specify that it will only be changing certain members of the
    > function, but I have only the following horrific way to do that. Can
    > someone please suggest a better alternative?
    >
    > #include <stdio.h>
    >
    > struct foo {
    > char *a;
    > char *b;
    > };
    >
    > struct const_foo {
    > const char *a;
    > const char *b;
    > };
    >
    > struct foo_const_a {
    > const char *a;
    > char *b;
    > };
    >
    > struct foo_const_b {
    > char *a;
    > const char *b;
    > };
    >
    > void modify_a(struct foo_const_b *f)
    > {
    > f->a = "a has been changed!";
    > }
    >
    > void modify_b(struct foo_const_a *f)
    > {
    > f->b = "b has been changed!";
    > }
    >
    > void print_foo(struct const_foo *f)
    > {
    > printf("f.a = %s\nf.b = %s\n", f->a, f->b);
    > }
    >
    > int main(void)
    > {
    > struct foo F = {"a string", "b string"};
    >
    > print_foo((struct const_foo*)&F);
    > modify_a((struct foo_const_b*)&F);
    > modify_b((struct foo_const_a*)&F);
    > print_foo((struct const_foo*)&F);
    >
    > return 0;
    > }
    >


    Since modify_b can't modify 'a' and modify_a can't modify 'b', why do you
    need to protect the other structure elements? Is there a data corruption
    issue here?

    If so, you might want to have two versions of the structure: "protected" and
    "unprotected". At a critical point in the program, copy the "protected"
    structure to the "unprotected" one. Modify elements of the "unprotected"
    structure via a normal routine or assignment. When done, you have a few
    choices. You could discard the "unprotected" structure, copy the
    "unprotected" structure to the "protected" one, copy the modified element
    from the "unprotected" structure to the "protected", or compare the
    structures to see what's going wrong.


    Rod Pemberton
     
    Rod Pemberton, May 2, 2006
    #2
    1. Advertising

  3. On 1 May 2006 12:19:48 -0700, "Bill Pursell" <>
    wrote:

    >Suppose I have a structure with many members, and I pass a pointer to
    >that structure to a function. I'd like the prototype of the function
    >to specify that it will only be changing certain members of the
    >function, but I have only the following horrific way to do that. Can
    >someone please suggest a better alternative?
    >
    >#include <stdio.h>
    >
    >struct foo {
    > char *a;
    > char *b;
    >};
    >
    >struct const_foo {
    > const char *a;
    > const char *b;
    >};
    >
    >struct foo_const_a {
    > const char *a;
    > char *b;
    >};
    >
    >struct foo_const_b {
    > char *a;
    > const char *b;
    >};
    >
    >void modify_a(struct foo_const_b *f)
    >{
    > f->a = "a has been changed!";
    >}
    >
    >void modify_b(struct foo_const_a *f)
    >{
    > f->b = "b has been changed!";
    >}
    >
    >void print_foo(struct const_foo *f)
    >{
    > printf("f.a = %s\nf.b = %s\n", f->a, f->b);
    >}
    >
    >int main(void)
    >{
    > struct foo F = {"a string", "b string"};
    >
    > print_foo((struct const_foo*)&F);


    Unfortunately, this need not work. You have no guarantee that the
    padding, or lack of same, in a struct foo is the same as that in a
    struct const_foo). offsetof(struct foo,b) could be 4 while
    offsetof(struct const_foo,b) could be 8. Unlikely, I admit, but still
    possible, especially on the DS9000.
    > modify_a((struct foo_const_b*)&F);
    > modify_b((struct foo_const_a*)&F);
    > print_foo((struct const_foo*)&F);
    >
    > return 0;
    >}



    Remove del for email
     
    Barry Schwarz, May 2, 2006
    #3
  4. Bill Pursell

    Bill Pursell Guest

    Rod Pemberton wrote:
    > "Bill Pursell" <> wrote in message
    > news:...
    > > Suppose I have a structure with many members, and I pass a pointer to
    > > that structure to a function. I'd like the prototype of the function
    > > to specify that it will only be changing certain members of the
    > > function, but I have only the following horrific way to do that. Can
    > > someone please suggest a better alternative?
    > >
    > > #include <stdio.h>
    > >
    > > struct foo {
    > > char *a;
    > > char *b;
    > > };
    > >
    > > struct const_foo {
    > > const char *a;
    > > const char *b;
    > > };
    > >
    > > struct foo_const_a {
    > > const char *a;
    > > char *b;
    > > };
    > >
    > > struct foo_const_b {
    > > char *a;
    > > const char *b;
    > > };
    > >
    > > void modify_a(struct foo_const_b *f)
    > > {
    > > f->a = "a has been changed!";
    > > }
    > >
    > > void modify_b(struct foo_const_a *f)
    > > {
    > > f->b = "b has been changed!";
    > > }
    > >
    > > void print_foo(struct const_foo *f)
    > > {
    > > printf("f.a = %s\nf.b = %s\n", f->a, f->b);
    > > }
    > >
    > > int main(void)
    > > {
    > > struct foo F = {"a string", "b string"};
    > >
    > > print_foo((struct const_foo*)&F);
    > > modify_a((struct foo_const_b*)&F);
    > > modify_b((struct foo_const_a*)&F);
    > > print_foo((struct const_foo*)&F);
    > >
    > > return 0;
    > > }
    > >

    >
    > Since modify_b can't modify 'a' and modify_a can't modify 'b', why do you
    > need to protect the other structure elements? Is there a data corruption
    > issue here?
    >


    There's no data corruption problem, I just observed that in many
    instances I have data structures with several buffers getting passed
    into functions, and the only manner by which I can tell which function
    modifies which buffer is to inspect the function body/comments. I
    could modify the protoypes to specify that the struct is constant, but
    that of course gives no assurance on the contents of foo->a. I suppose
    the only other solution is to define the structure as having const
    members and making it difficult to assign/modify things. Something
    like:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    struct foo {
    const char *a;
    const char *b;
    };

    void
    print_foo(const struct foo *f)
    {
    printf("f.a = %s\n", f->a);
    printf("f.b = %s\n", f->b);
    }

    void
    modify(const struct foo *f, char *dest)
    {
    const char *src = f->a;
    dest[0] = src[0]+1;
    }

    int
    main(void)
    {
    struct foo f;
    f.a = malloc(20);
    f.b = malloc(20);
    if (f.a == NULL || f.b == NULL)
    perror(0), exit(-1);

    strcpy((char *)f.a, "string a");
    strcpy((char *)f.b, "string b");

    print_foo(&f);
    modify(&f, (char *)f.b);
    print_foo(&f);
    return 0;
    }


    The trouble with this is that modify() (or print_foo()!) could be still
    be written to do:
    ((char *)f->a)[3]++;
    but that's pathologically poor coding, so I can avoid that. In this
    instance, the caller is doing all the casting, so it's fairly clear
    from context which members are being modified.
     
    Bill Pursell, May 2, 2006
    #4
  5. "Bill Pursell" <> wrote in message
    news:...
    > Rod Pemberton wrote:
    > > "Bill Pursell" <> wrote in message
    > > news:...
    > > > Suppose I have a structure with many members, and I pass a pointer to
    > > > that structure to a function. I'd like the prototype of the function
    > > > to specify that it will only be changing certain members of the
    > > > function, but I have only the following horrific way to do that. Can
    > > > someone please suggest a better alternative?
    > > >

    > >
    > > Since modify_b can't modify 'a' and modify_a can't modify 'b', why do

    you
    > > need to protect the other structure elements? Is there a data

    corruption
    > > issue here?
    > >

    >
    > There's no data corruption problem, I just observed that in many
    > instances I have data structures with several buffers getting passed
    > into functions, and the only manner by which I can tell which function
    > modifies which buffer is to inspect the function body/comments. I
    > could modify the protoypes to specify that the struct is constant, but
    > that of course gives no assurance on the contents of foo->a. I suppose
    > the only other solution is to define the structure as having const
    > members and making it difficult to assign/modify things. Something
    > like:
    >
    >


    It seems that you are trying to create C features with may be available in
    C++. I know very little about C++, but IIRC, you can implement data
    protection due to the object oriented feature of binding code with data.
    The code gets executed for each action on the data. Which means, you can
    prevent variables from being multiply assigned, set, reset or whatever...
    Perhaps you might look into using a small amount of C++.


    Rod Pemberton
     
    Rod Pemberton, May 2, 2006
    #5
  6. On 1 May 2006 12:19:48 -0700, "Bill Pursell" <>
    wrote:

    > Suppose I have a structure with many members, and I pass a pointer to
    > that structure to a function. I'd like the prototype of the function
    > to specify that it will only be changing certain members of the
    > function, but I have only the following horrific way to do that. Can
    > someone please suggest a better alternative?
    >
    > #include <stdio.h>
    >
    > struct foo {
    > char *a;
    > char *b;
    > };
    >
    > struct const_foo {
    > const char *a;
    > const char *b;
    > };
    >
    > struct foo_const_a {
    > const char *a;
    > char *b;
    > };
    >
    > struct foo_const_b {
    > char *a;
    > const char *b;
    > };
    >
    > void modify_a(struct foo_const_b *f)
    > {
    > f->a = "a has been changed!";
    > }
    >
    > void modify_b(struct foo_const_a *f)
    > {
    > f->b = "b has been changed!";
    > }
    >

    Those don't (even) do what you asked for. What you declared const is
    the data pointed to by the struct member e.g. a, not the member a
    itself. In your modify_a (struct foo_const_b *f)
    f->b = something would work with no (required) complaint.
    You wanted
    struct foo_const_a { char * const a; char * b; };
    etc.

    As already noted, formally these 'slightly different' structs are not
    required to be 'compatible' i.e. laid out the same, although I don't
    see any plausible reason an implementation would not do so.

    And as you already noted, there is nothing to prevent the called
    routine from casting away these 'partial consts', so in general you're
    going to have to read the code of those functions anyway. Ideally you
    (or whoever) should give the functions, and sometimes their
    interface/prototype parameters, names that accurately describe what
    they do, so just by looking at them you can tell. That's not always
    easy to do however, especially in code that has evolved (and often
    deteriorated) over time, changes, and (supposed) enhancements.
    If the routines/library you are calling are in really bad shape, you
    might be better off just rewriting up to scratch. Your call.

    - David.Thompson1 at worldnet.att.net
     
    Dave Thompson, May 11, 2006
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Rakesh Sinha
    Replies:
    4
    Views:
    1,855
    Rakesh Sinha
    Jan 13, 2005
  2. Mas

    C - Const Struct Members

    Mas, Dec 4, 2005, in forum: C Programming
    Replies:
    1
    Views:
    490
    Eric Sosman
    Dec 4, 2005
  3. Susan Baker
    Replies:
    2
    Views:
    517
    Alf P. Steinbach
    Jul 3, 2005
  4. Javier
    Replies:
    2
    Views:
    574
    James Kanze
    Sep 4, 2007
  5. John Reye
    Replies:
    28
    Views:
    1,381
    Tim Rentsch
    May 8, 2012
Loading...

Share This Page