const struct *

Discussion in 'C Programming' started by bill, Nov 16, 2005.

  1. bill

    bill Guest

    I recently realized that I have a structure that I'd like to put more
    protection on in the following sense: I'd like to modify

    struct foo{
    int *x;
    } ;

    to be:
    struct foo {
    const int *x;
    }

    I see only 2 choices (3 if I count not making the change):
    1) modify the structure and all functions that initialize instances of
    it
    2) define struct const_foo {const int *x;}, change the formal
    parameter list of all functions that used to take a const foo *
    argument to take a const const_foo * instead, and cast all
    calls.

    I'm not particularly fond of either solution. #1 is aesthetically
    appealing (ie, it's the proper thing to do), #2 would be much
    faster to implement in this case, but seems to be a kludge.
    It seems as if I'm implementing the const keyword to
    make "const foo *" mean "const foo */w const *x" and
    is pretty ugly.

    Can anyone suggest another solution?
    bill, Nov 16, 2005
    #1
    1. Advertising

  2. bill

    Madguy Guest

    are you sure that changing int *i to const int *i make any error? i
    think it will not . it'll make errors only if you assing 'i' any value
    twice.
    Madguy, Nov 16, 2005
    #2
    1. Advertising

  3. bill

    bill Guest

    Madguy wrote:
    > are you sure that changing int *i to const int *i make any error? i
    > think it will not . it'll make errors only if you assing 'i' any value
    > twice.


    Things won't even compile if i simply add "const". Consider
    the following code:

    typedef struct { int *x;} foo_t;

    void foo(foo_t *x){ *x->x = 3;}

    int main()
    {
    foo_t x;
    foo(&x);
    return 0;
    }

    If you simply make to foo_t.x a const, then foo() is
    writing to a read-only location. I think I'm actually asking a
    slightly
    more generic question:

    suppose I have
    struct foo_s {
    int *a, *b, *c;
    };

    I want 3 functions, A(), B(), and C() which each take
    a struct foo_s as an argument. A will only modify *a,
    B will only modify *b, and C will only modify *c.
    I'd like to reflect those facts in the parameter list
    with const. The only solution I see for that is to
    delcare 3 different structure types with const in
    the appropriate place, and then either cast the
    parameter for each call, or specify the parameter
    as a void * and cast it within each function.
    bill, Nov 16, 2005
    #3
  4. bill

    Chris Dollin Guest

    bill wrote:

    > If you simply make to foo_t.x a const, then foo() is
    > writing to a read-only location. I think I'm actually asking a
    > slightly
    > more generic question:
    >
    > suppose I have
    > struct foo_s {
    > int *a, *b, *c;
    > };
    >
    > I want 3 functions, A(), B(), and C() which each take
    > a struct foo_s as an argument. A will only modify *a,
    > B will only modify *b, and C will only modify *c.
    > I'd like to reflect those facts in the parameter list
    > with const. The only solution I see for that is to
    > delcare 3 different structure types with const in
    > the appropriate place, and then either cast the
    > parameter for each call, or specify the parameter
    > as a void * and cast it within each function.


    You could do the following:

    void A( const struct foo_s *p, int **toAlter )
    {
    ... look hard a *p, update *toAlter
    }

    ....
    A( &someStructFooS, &someStructFooS.a );

    Similarly for B & C.


    --
    Chris "another virtual machine" Dollin
    time is just space under pressure.
    Chris Dollin, Nov 16, 2005
    #4
  5. bill

    bill Guest

    bill wrote:

    > suppose I have
    > struct foo_s {
    > int *a, *b, *c;
    > };
    >
    > I want 3 functions, A(), B(), and C() which each take
    > a struct foo_s as an argument. A will only modify *a,
    > B will only modify *b, and C will only modify *c.
    > I'd like to reflect those facts in the parameter list
    > with const. The only solution I see for that is to
    > delcare 3 different structure types with const in
    > the appropriate place, and then either cast the
    > parameter for each call, or specify the parameter
    > as a void * and cast it within each function.


    That actually works very nicely, but it's not immediately
    clear from the function declaration what's going on. The following
    code won't compile, due to the illegal assignement (which is
    desirable). However, the function declaration just has "void *"
    and you have to look in the function to see what members
    of the structure are constant. Any ideas on how to improve this?
    (I'm not willing to simply declare the formal parameter of type
    x_foo_t without casting all the calls, as I will not accept compile
    time warnings. I am willing to do specific warning suppression,
    but I don't think that's possible. (ie, tag the function with an
    attribute indictating that this particular function shouldn't
    generate that particular warning). Can that be done?)

    typedef struct {
    int *x;
    int *y;
    int *z;
    } foo_t;

    typedef struct { /* use this struct when only modifying *x */
    int *x;
    const int *y;
    const int *z;
    } x_foo_t;

    void
    mod_x(void *A)
    {
    x_foo_t *a = (x_foo_t*) A;
    *a->x = 3;
    *a->y = 3; /* compile time error!! */
    }

    int
    main()
    {
    int a[1],b[1],c[1];
    foo_t x;
    x.x = a; x.y=b, x.z=c;
    mod_x(&x);
    printf("x=%d, y=%d, z=%d\n", *x.x, *x.y, *x.z);
    return 0;
    bill, Nov 16, 2005
    #5
  6. bill

    bill Guest

    Chris Dollin wrote:
    > bill wrote:
    >
    > > If you simply make to foo_t.x a const, then foo() is
    > > writing to a read-only location. I think I'm actually asking a
    > > slightly
    > > more generic question:
    > >
    > > suppose I have
    > > struct foo_s {
    > > int *a, *b, *c;
    > > };
    > >
    > > I want 3 functions, A(), B(), and C() which each take
    > > a struct foo_s as an argument. A will only modify *a,
    > > B will only modify *b, and C will only modify *c.
    > > I'd like to reflect those facts in the parameter list
    > > with const. The only solution I see for that is to
    > > delcare 3 different structure types with const in
    > > the appropriate place, and then either cast the
    > > parameter for each call, or specify the parameter
    > > as a void * and cast it within each function.

    >
    > You could do the following:
    >
    > void A( const struct foo_s *p, int **toAlter )
    > {
    > ... look hard a *p, update *toAlter
    > }
    >
    > ...
    > A( &someStructFooS, &someStructFooS.a );
    >
    > Similarly for B & C.
    >
    >


    I like that idea, but I can't seem to get around the compiler
    warning that I'm discarding the qualifier. When I make the call:
    A(&p, &p.x), attempting to alter p.x, I need to cast it as
    A(&p, (int *)&p.x). That method makes it clearer from
    the declaration, so that's a good thing. There's probably
    no way to avoid the cast.... (eventually, the compiler warnings
    will all get casted away....yeah, right)
    bill, Nov 16, 2005
    #6
  7. bill

    Chris Dollin Guest

    bill wrote:

    > Chris Dollin wrote:
    >> bill wrote:
    >>
    >> > If you simply make to foo_t.x a const, then foo() is
    >> > writing to a read-only location. I think I'm actually asking a
    >> > slightly
    >> > more generic question:
    >> >
    >> > suppose I have
    >> > struct foo_s {
    >> > int *a, *b, *c;
    >> > };
    >> >
    >> > I want 3 functions, A(), B(), and C() which each take
    >> > a struct foo_s as an argument. A will only modify *a,
    >> > B will only modify *b, and C will only modify *c.
    >> > I'd like to reflect those facts in the parameter list
    >> > with const. The only solution I see for that is to
    >> > delcare 3 different structure types with const in
    >> > the appropriate place, and then either cast the
    >> > parameter for each call, or specify the parameter
    >> > as a void * and cast it within each function.

    >>
    >> You could do the following:
    >>
    >> void A( const struct foo_s *p, int **toAlter )
    >> {
    >> ... look hard a *p, update *toAlter
    >> }
    >>
    >> ...
    >> A( &someStructFooS, &someStructFooS.a );
    >>
    >> Similarly for B & C.
    >>
    >>

    >
    > I like that idea, but I can't seem to get around the compiler
    > warning that I'm discarding the qualifier. When I make the call:
    > A(&p, &p.x), attempting to alter p.x, I need to cast it as
    > A(&p, (int *)&p.x). That method makes it clearer from
    > the declaration, so that's a good thing. There's probably
    > no way to avoid the cast.... (eventually, the compiler warnings
    > will all get casted away....yeah, right)


    I suspect you've declared the struct as a const. You don't need to
    to satisfy your request above starting "I want 3 functions, A(), B(),
    and C()". Presumably there's more context than I know.

    --
    Chris "another virtual machine" Dollin
    time is just space under pressure.
    Chris Dollin, Nov 16, 2005
    #7
    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. Replies:
    11
    Views:
    1,089
  2. Javier
    Replies:
    2
    Views:
    547
    James Kanze
    Sep 4, 2007
  3. 0m
    Replies:
    26
    Views:
    1,095
    Tim Rentsch
    Nov 10, 2008
  4. fungus
    Replies:
    13
    Views:
    873
    fungus
    Oct 31, 2008
  5. Replies:
    2
    Views:
    530
    Andrew Koenig
    Feb 9, 2009
Loading...

Share This Page