Pointer to a const structure, can members still be modified?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
13
down vote

favorite
3












I have a structure which I want to pass to some external c code via some callback function that they register with my program. However, I want to pass that structure as read-only. My concern is that they can still modify the structures which I have pointer to inside the original structure that I pass. Explained with small example below:



struct s1 
int a;
int b;
;

struct s2
int x;
struct s1 *y;
;

void f(const struct s2 *o)

//o->x=10; //error
o->y->a=20; //no error
o->y->b=30; //no error


int main()

struct s1 o1 = 10, 20;
struct s2 o2 = 30, &o1;
f(&o2);



So, How do I improve my code design so that they cannot modify anything w.r.t the structure I pass?







share|improve this question






















  • Do you want to allow them to read some parameters? If not, you may use forward declaration approach to hide some members from public code, make it visible only in private section of your library. Based on your answer I will give you official answer.
    – tilz0R
    Aug 10 at 7:30










  • What you can do is define the struct in a .c file. From all header function you typedef a void* for your type and other functions that belong to a public api of you type. Then from the callback you cannot see the members and only use the public functions of the type.
    – hetepeperfan
    Aug 10 at 7:30










  • @tilz0R Yes, they should be able to read all the members. They'll take different actions depending on what the value of that member is.
    – Raman
    Aug 10 at 7:34






  • 2




    To fully hide, you will have to create getter functions in your library.
    – tilz0R
    Aug 10 at 7:36














up vote
13
down vote

favorite
3












I have a structure which I want to pass to some external c code via some callback function that they register with my program. However, I want to pass that structure as read-only. My concern is that they can still modify the structures which I have pointer to inside the original structure that I pass. Explained with small example below:



struct s1 
int a;
int b;
;

struct s2
int x;
struct s1 *y;
;

void f(const struct s2 *o)

//o->x=10; //error
o->y->a=20; //no error
o->y->b=30; //no error


int main()

struct s1 o1 = 10, 20;
struct s2 o2 = 30, &o1;
f(&o2);



So, How do I improve my code design so that they cannot modify anything w.r.t the structure I pass?







share|improve this question






















  • Do you want to allow them to read some parameters? If not, you may use forward declaration approach to hide some members from public code, make it visible only in private section of your library. Based on your answer I will give you official answer.
    – tilz0R
    Aug 10 at 7:30










  • What you can do is define the struct in a .c file. From all header function you typedef a void* for your type and other functions that belong to a public api of you type. Then from the callback you cannot see the members and only use the public functions of the type.
    – hetepeperfan
    Aug 10 at 7:30










  • @tilz0R Yes, they should be able to read all the members. They'll take different actions depending on what the value of that member is.
    – Raman
    Aug 10 at 7:34






  • 2




    To fully hide, you will have to create getter functions in your library.
    – tilz0R
    Aug 10 at 7:36












up vote
13
down vote

favorite
3









up vote
13
down vote

favorite
3






3





I have a structure which I want to pass to some external c code via some callback function that they register with my program. However, I want to pass that structure as read-only. My concern is that they can still modify the structures which I have pointer to inside the original structure that I pass. Explained with small example below:



struct s1 
int a;
int b;
;

struct s2
int x;
struct s1 *y;
;

void f(const struct s2 *o)

//o->x=10; //error
o->y->a=20; //no error
o->y->b=30; //no error


int main()

struct s1 o1 = 10, 20;
struct s2 o2 = 30, &o1;
f(&o2);



So, How do I improve my code design so that they cannot modify anything w.r.t the structure I pass?







share|improve this question














I have a structure which I want to pass to some external c code via some callback function that they register with my program. However, I want to pass that structure as read-only. My concern is that they can still modify the structures which I have pointer to inside the original structure that I pass. Explained with small example below:



struct s1 
int a;
int b;
;

struct s2
int x;
struct s1 *y;
;

void f(const struct s2 *o)

//o->x=10; //error
o->y->a=20; //no error
o->y->b=30; //no error


int main()

struct s1 o1 = 10, 20;
struct s2 o2 = 30, &o1;
f(&o2);



So, How do I improve my code design so that they cannot modify anything w.r.t the structure I pass?









share|improve this question













share|improve this question




share|improve this question








edited Aug 10 at 7:24

























asked Aug 10 at 7:12









Raman

1,5361230




1,5361230











  • Do you want to allow them to read some parameters? If not, you may use forward declaration approach to hide some members from public code, make it visible only in private section of your library. Based on your answer I will give you official answer.
    – tilz0R
    Aug 10 at 7:30










  • What you can do is define the struct in a .c file. From all header function you typedef a void* for your type and other functions that belong to a public api of you type. Then from the callback you cannot see the members and only use the public functions of the type.
    – hetepeperfan
    Aug 10 at 7:30










  • @tilz0R Yes, they should be able to read all the members. They'll take different actions depending on what the value of that member is.
    – Raman
    Aug 10 at 7:34






  • 2




    To fully hide, you will have to create getter functions in your library.
    – tilz0R
    Aug 10 at 7:36
















  • Do you want to allow them to read some parameters? If not, you may use forward declaration approach to hide some members from public code, make it visible only in private section of your library. Based on your answer I will give you official answer.
    – tilz0R
    Aug 10 at 7:30










  • What you can do is define the struct in a .c file. From all header function you typedef a void* for your type and other functions that belong to a public api of you type. Then from the callback you cannot see the members and only use the public functions of the type.
    – hetepeperfan
    Aug 10 at 7:30










  • @tilz0R Yes, they should be able to read all the members. They'll take different actions depending on what the value of that member is.
    – Raman
    Aug 10 at 7:34






  • 2




    To fully hide, you will have to create getter functions in your library.
    – tilz0R
    Aug 10 at 7:36















Do you want to allow them to read some parameters? If not, you may use forward declaration approach to hide some members from public code, make it visible only in private section of your library. Based on your answer I will give you official answer.
– tilz0R
Aug 10 at 7:30




Do you want to allow them to read some parameters? If not, you may use forward declaration approach to hide some members from public code, make it visible only in private section of your library. Based on your answer I will give you official answer.
– tilz0R
Aug 10 at 7:30












What you can do is define the struct in a .c file. From all header function you typedef a void* for your type and other functions that belong to a public api of you type. Then from the callback you cannot see the members and only use the public functions of the type.
– hetepeperfan
Aug 10 at 7:30




What you can do is define the struct in a .c file. From all header function you typedef a void* for your type and other functions that belong to a public api of you type. Then from the callback you cannot see the members and only use the public functions of the type.
– hetepeperfan
Aug 10 at 7:30












@tilz0R Yes, they should be able to read all the members. They'll take different actions depending on what the value of that member is.
– Raman
Aug 10 at 7:34




@tilz0R Yes, they should be able to read all the members. They'll take different actions depending on what the value of that member is.
– Raman
Aug 10 at 7:34




2




2




To fully hide, you will have to create getter functions in your library.
– tilz0R
Aug 10 at 7:36




To fully hide, you will have to create getter functions in your library.
– tilz0R
Aug 10 at 7:36












5 Answers
5






active

oldest

votes

















up vote
8
down vote



accepted










To properly handle this situation, you can only use forward declaration to hide members together with getter and setter functions.



Focus on code below and check:




  • struct s1 only has forward declaration so you can make a pointer to it in struct s2.

  • Actual implementation of struct s1 is in mylib.c thus all members are only visible to your library and not to user.

  • Getters and setters are implemented to set/read the value to these hidden members as only your library has access to members, making it completely hidden from user.

  • This forces him to use your functions.

mylib.h:



#ifndef __MYLIB_H
#define __MYLIB_H

//Create forward declaration only
//Implementation is in .c file
struct s1;

//Create user structure
struct s2
int x;
struct s1* y;
;

int get_a_from_s1(struct s2* s);
void set_a_to_s1(struct s2* s, int a);

#endif /* __MYLIB_H */


mylib.c:



#include "mylib.h"

//Now implement structure
struct s1
int a, b;
;

//Make getter
int
get_a_from_s1(struct s2* s)
return s->y->a;


//Make setter
void
set_a_to_s1(struct s2* s, int a)
s->y->a = a;



main.c:



#include <stdio.h>
#include "mylib.h"

int main(void)
struct s2 s;
int a;

....

s.y->a = 5; //error

//Set s1.a value from s2 structure
set_a_to_s1(&s, 10); //OK

//To view members of s1 inside s2, create member functions
a = get_a_from_s1(&s); //OK

printf("a: %drn", a);

return 0;



Of course, please make sure that ->y is not NULL or you have undefined behavior.






share|improve this answer


















  • 2




    For the record, this kind of design pattern with incomplete type of struct s1 in the header is called opaque type or opaque pointers.
    – Lundin
    Aug 10 at 9:41

















up vote
5
down vote













You cannot. Even if you pass the struct s2 by value, you will get in the function a pointer to a non const struct s1, simply because it is what s2 contains per its definition.



And once you have a pointer to a non const object you can change that object. What I mean here and what other answers mean, is that it is not a language problem - more exactly the language can nothing for you here - but a design problem. If for any reason it is not acceptable that the struct s1 can be changed from f then you have to find a different design where you do not pass a non const pointer to it, be it member of a const struct or not. Here a simple way would be to pass the individual members:



void f(int x, const struct s1 *y) 
y->a = 20; // error



It may not be what you expect, but it is the best I can say for C language.






share|improve this answer




















  • Yes, I also think that passing all members one by one is the only way.
    – Raman
    Aug 10 at 7:36

















up vote
4
down vote













You can change the second struct declaration like so:



struct s2 
int x;
struct s1 const *y;
;


The added const ensures that y is read-only.






share|improve this answer




















  • Yes, But that way I myself can't modify y.
    – Raman
    Aug 10 at 7:19










  • Yes, you can if you cast it back! ((struct s1 *) (o->y))->b=30;
    – memo
    Aug 10 at 7:21










  • @It'scominghome One scenario would be if you want to publish it as part of an API or library and make sure that users of it don't change it accidentally.
    – memo
    Aug 10 at 7:23






  • 1




    @memo very ugly and may introduce undefined behavior.
    – tilz0R
    Aug 10 at 7:25






  • 1




    @tilz0R I just answered the question, not that I would recommend it
    – memo
    Aug 10 at 7:27

















up vote
0
down vote













I would write another function that takes in a const struct s1 * to modify the values of s1.






share|improve this answer



























    up vote
    0
    down vote













    In f(), const struct s2 *o means in the struct s2 being pointed to by o, the values of its members ie, x and y cannot be changed.



    With o->y->a=20, you are not modifying the value of y. You are just using that address to modify a member of the structure being pointed to by y and y's value, which is an address, remains the same.



    So those 2 lines will give no error.



    I could see no way to avoid this unless you could make the struct s2 definition to



    struct s2 
    int x;
    const struct s1 *y;
    ;


    in which case y is a pointer to a constant struct s1.



    See the spiral rule and visit the cdecl website.






    share|improve this answer




















      Your Answer





      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "1"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      convertImagesToLinks: true,
      noModals: false,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













       

      draft saved


      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f51780954%2fpointer-to-a-const-structure-can-members-still-be-modified%23new-answer', 'question_page');

      );

      Post as a guest






























      5 Answers
      5






      active

      oldest

      votes








      5 Answers
      5






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      8
      down vote



      accepted










      To properly handle this situation, you can only use forward declaration to hide members together with getter and setter functions.



      Focus on code below and check:




      • struct s1 only has forward declaration so you can make a pointer to it in struct s2.

      • Actual implementation of struct s1 is in mylib.c thus all members are only visible to your library and not to user.

      • Getters and setters are implemented to set/read the value to these hidden members as only your library has access to members, making it completely hidden from user.

      • This forces him to use your functions.

      mylib.h:



      #ifndef __MYLIB_H
      #define __MYLIB_H

      //Create forward declaration only
      //Implementation is in .c file
      struct s1;

      //Create user structure
      struct s2
      int x;
      struct s1* y;
      ;

      int get_a_from_s1(struct s2* s);
      void set_a_to_s1(struct s2* s, int a);

      #endif /* __MYLIB_H */


      mylib.c:



      #include "mylib.h"

      //Now implement structure
      struct s1
      int a, b;
      ;

      //Make getter
      int
      get_a_from_s1(struct s2* s)
      return s->y->a;


      //Make setter
      void
      set_a_to_s1(struct s2* s, int a)
      s->y->a = a;



      main.c:



      #include <stdio.h>
      #include "mylib.h"

      int main(void)
      struct s2 s;
      int a;

      ....

      s.y->a = 5; //error

      //Set s1.a value from s2 structure
      set_a_to_s1(&s, 10); //OK

      //To view members of s1 inside s2, create member functions
      a = get_a_from_s1(&s); //OK

      printf("a: %drn", a);

      return 0;



      Of course, please make sure that ->y is not NULL or you have undefined behavior.






      share|improve this answer


















      • 2




        For the record, this kind of design pattern with incomplete type of struct s1 in the header is called opaque type or opaque pointers.
        – Lundin
        Aug 10 at 9:41














      up vote
      8
      down vote



      accepted










      To properly handle this situation, you can only use forward declaration to hide members together with getter and setter functions.



      Focus on code below and check:




      • struct s1 only has forward declaration so you can make a pointer to it in struct s2.

      • Actual implementation of struct s1 is in mylib.c thus all members are only visible to your library and not to user.

      • Getters and setters are implemented to set/read the value to these hidden members as only your library has access to members, making it completely hidden from user.

      • This forces him to use your functions.

      mylib.h:



      #ifndef __MYLIB_H
      #define __MYLIB_H

      //Create forward declaration only
      //Implementation is in .c file
      struct s1;

      //Create user structure
      struct s2
      int x;
      struct s1* y;
      ;

      int get_a_from_s1(struct s2* s);
      void set_a_to_s1(struct s2* s, int a);

      #endif /* __MYLIB_H */


      mylib.c:



      #include "mylib.h"

      //Now implement structure
      struct s1
      int a, b;
      ;

      //Make getter
      int
      get_a_from_s1(struct s2* s)
      return s->y->a;


      //Make setter
      void
      set_a_to_s1(struct s2* s, int a)
      s->y->a = a;



      main.c:



      #include <stdio.h>
      #include "mylib.h"

      int main(void)
      struct s2 s;
      int a;

      ....

      s.y->a = 5; //error

      //Set s1.a value from s2 structure
      set_a_to_s1(&s, 10); //OK

      //To view members of s1 inside s2, create member functions
      a = get_a_from_s1(&s); //OK

      printf("a: %drn", a);

      return 0;



      Of course, please make sure that ->y is not NULL or you have undefined behavior.






      share|improve this answer


















      • 2




        For the record, this kind of design pattern with incomplete type of struct s1 in the header is called opaque type or opaque pointers.
        – Lundin
        Aug 10 at 9:41












      up vote
      8
      down vote



      accepted







      up vote
      8
      down vote



      accepted






      To properly handle this situation, you can only use forward declaration to hide members together with getter and setter functions.



      Focus on code below and check:




      • struct s1 only has forward declaration so you can make a pointer to it in struct s2.

      • Actual implementation of struct s1 is in mylib.c thus all members are only visible to your library and not to user.

      • Getters and setters are implemented to set/read the value to these hidden members as only your library has access to members, making it completely hidden from user.

      • This forces him to use your functions.

      mylib.h:



      #ifndef __MYLIB_H
      #define __MYLIB_H

      //Create forward declaration only
      //Implementation is in .c file
      struct s1;

      //Create user structure
      struct s2
      int x;
      struct s1* y;
      ;

      int get_a_from_s1(struct s2* s);
      void set_a_to_s1(struct s2* s, int a);

      #endif /* __MYLIB_H */


      mylib.c:



      #include "mylib.h"

      //Now implement structure
      struct s1
      int a, b;
      ;

      //Make getter
      int
      get_a_from_s1(struct s2* s)
      return s->y->a;


      //Make setter
      void
      set_a_to_s1(struct s2* s, int a)
      s->y->a = a;



      main.c:



      #include <stdio.h>
      #include "mylib.h"

      int main(void)
      struct s2 s;
      int a;

      ....

      s.y->a = 5; //error

      //Set s1.a value from s2 structure
      set_a_to_s1(&s, 10); //OK

      //To view members of s1 inside s2, create member functions
      a = get_a_from_s1(&s); //OK

      printf("a: %drn", a);

      return 0;



      Of course, please make sure that ->y is not NULL or you have undefined behavior.






      share|improve this answer














      To properly handle this situation, you can only use forward declaration to hide members together with getter and setter functions.



      Focus on code below and check:




      • struct s1 only has forward declaration so you can make a pointer to it in struct s2.

      • Actual implementation of struct s1 is in mylib.c thus all members are only visible to your library and not to user.

      • Getters and setters are implemented to set/read the value to these hidden members as only your library has access to members, making it completely hidden from user.

      • This forces him to use your functions.

      mylib.h:



      #ifndef __MYLIB_H
      #define __MYLIB_H

      //Create forward declaration only
      //Implementation is in .c file
      struct s1;

      //Create user structure
      struct s2
      int x;
      struct s1* y;
      ;

      int get_a_from_s1(struct s2* s);
      void set_a_to_s1(struct s2* s, int a);

      #endif /* __MYLIB_H */


      mylib.c:



      #include "mylib.h"

      //Now implement structure
      struct s1
      int a, b;
      ;

      //Make getter
      int
      get_a_from_s1(struct s2* s)
      return s->y->a;


      //Make setter
      void
      set_a_to_s1(struct s2* s, int a)
      s->y->a = a;



      main.c:



      #include <stdio.h>
      #include "mylib.h"

      int main(void)
      struct s2 s;
      int a;

      ....

      s.y->a = 5; //error

      //Set s1.a value from s2 structure
      set_a_to_s1(&s, 10); //OK

      //To view members of s1 inside s2, create member functions
      a = get_a_from_s1(&s); //OK

      printf("a: %drn", a);

      return 0;



      Of course, please make sure that ->y is not NULL or you have undefined behavior.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Aug 10 at 9:46

























      answered Aug 10 at 7:43









      tilz0R

      5,32711131




      5,32711131







      • 2




        For the record, this kind of design pattern with incomplete type of struct s1 in the header is called opaque type or opaque pointers.
        – Lundin
        Aug 10 at 9:41












      • 2




        For the record, this kind of design pattern with incomplete type of struct s1 in the header is called opaque type or opaque pointers.
        – Lundin
        Aug 10 at 9:41







      2




      2




      For the record, this kind of design pattern with incomplete type of struct s1 in the header is called opaque type or opaque pointers.
      – Lundin
      Aug 10 at 9:41




      For the record, this kind of design pattern with incomplete type of struct s1 in the header is called opaque type or opaque pointers.
      – Lundin
      Aug 10 at 9:41












      up vote
      5
      down vote













      You cannot. Even if you pass the struct s2 by value, you will get in the function a pointer to a non const struct s1, simply because it is what s2 contains per its definition.



      And once you have a pointer to a non const object you can change that object. What I mean here and what other answers mean, is that it is not a language problem - more exactly the language can nothing for you here - but a design problem. If for any reason it is not acceptable that the struct s1 can be changed from f then you have to find a different design where you do not pass a non const pointer to it, be it member of a const struct or not. Here a simple way would be to pass the individual members:



      void f(int x, const struct s1 *y) 
      y->a = 20; // error



      It may not be what you expect, but it is the best I can say for C language.






      share|improve this answer




















      • Yes, I also think that passing all members one by one is the only way.
        – Raman
        Aug 10 at 7:36














      up vote
      5
      down vote













      You cannot. Even if you pass the struct s2 by value, you will get in the function a pointer to a non const struct s1, simply because it is what s2 contains per its definition.



      And once you have a pointer to a non const object you can change that object. What I mean here and what other answers mean, is that it is not a language problem - more exactly the language can nothing for you here - but a design problem. If for any reason it is not acceptable that the struct s1 can be changed from f then you have to find a different design where you do not pass a non const pointer to it, be it member of a const struct or not. Here a simple way would be to pass the individual members:



      void f(int x, const struct s1 *y) 
      y->a = 20; // error



      It may not be what you expect, but it is the best I can say for C language.






      share|improve this answer




















      • Yes, I also think that passing all members one by one is the only way.
        – Raman
        Aug 10 at 7:36












      up vote
      5
      down vote










      up vote
      5
      down vote









      You cannot. Even if you pass the struct s2 by value, you will get in the function a pointer to a non const struct s1, simply because it is what s2 contains per its definition.



      And once you have a pointer to a non const object you can change that object. What I mean here and what other answers mean, is that it is not a language problem - more exactly the language can nothing for you here - but a design problem. If for any reason it is not acceptable that the struct s1 can be changed from f then you have to find a different design where you do not pass a non const pointer to it, be it member of a const struct or not. Here a simple way would be to pass the individual members:



      void f(int x, const struct s1 *y) 
      y->a = 20; // error



      It may not be what you expect, but it is the best I can say for C language.






      share|improve this answer












      You cannot. Even if you pass the struct s2 by value, you will get in the function a pointer to a non const struct s1, simply because it is what s2 contains per its definition.



      And once you have a pointer to a non const object you can change that object. What I mean here and what other answers mean, is that it is not a language problem - more exactly the language can nothing for you here - but a design problem. If for any reason it is not acceptable that the struct s1 can be changed from f then you have to find a different design where you do not pass a non const pointer to it, be it member of a const struct or not. Here a simple way would be to pass the individual members:



      void f(int x, const struct s1 *y) 
      y->a = 20; // error



      It may not be what you expect, but it is the best I can say for C language.







      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Aug 10 at 7:32









      Serge Ballesta

      72.6k955125




      72.6k955125











      • Yes, I also think that passing all members one by one is the only way.
        – Raman
        Aug 10 at 7:36
















      • Yes, I also think that passing all members one by one is the only way.
        – Raman
        Aug 10 at 7:36















      Yes, I also think that passing all members one by one is the only way.
      – Raman
      Aug 10 at 7:36




      Yes, I also think that passing all members one by one is the only way.
      – Raman
      Aug 10 at 7:36










      up vote
      4
      down vote













      You can change the second struct declaration like so:



      struct s2 
      int x;
      struct s1 const *y;
      ;


      The added const ensures that y is read-only.






      share|improve this answer




















      • Yes, But that way I myself can't modify y.
        – Raman
        Aug 10 at 7:19










      • Yes, you can if you cast it back! ((struct s1 *) (o->y))->b=30;
        – memo
        Aug 10 at 7:21










      • @It'scominghome One scenario would be if you want to publish it as part of an API or library and make sure that users of it don't change it accidentally.
        – memo
        Aug 10 at 7:23






      • 1




        @memo very ugly and may introduce undefined behavior.
        – tilz0R
        Aug 10 at 7:25






      • 1




        @tilz0R I just answered the question, not that I would recommend it
        – memo
        Aug 10 at 7:27














      up vote
      4
      down vote













      You can change the second struct declaration like so:



      struct s2 
      int x;
      struct s1 const *y;
      ;


      The added const ensures that y is read-only.






      share|improve this answer




















      • Yes, But that way I myself can't modify y.
        – Raman
        Aug 10 at 7:19










      • Yes, you can if you cast it back! ((struct s1 *) (o->y))->b=30;
        – memo
        Aug 10 at 7:21










      • @It'scominghome One scenario would be if you want to publish it as part of an API or library and make sure that users of it don't change it accidentally.
        – memo
        Aug 10 at 7:23






      • 1




        @memo very ugly and may introduce undefined behavior.
        – tilz0R
        Aug 10 at 7:25






      • 1




        @tilz0R I just answered the question, not that I would recommend it
        – memo
        Aug 10 at 7:27












      up vote
      4
      down vote










      up vote
      4
      down vote









      You can change the second struct declaration like so:



      struct s2 
      int x;
      struct s1 const *y;
      ;


      The added const ensures that y is read-only.






      share|improve this answer












      You can change the second struct declaration like so:



      struct s2 
      int x;
      struct s1 const *y;
      ;


      The added const ensures that y is read-only.







      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Aug 10 at 7:19









      memo

      1,274314




      1,274314











      • Yes, But that way I myself can't modify y.
        – Raman
        Aug 10 at 7:19










      • Yes, you can if you cast it back! ((struct s1 *) (o->y))->b=30;
        – memo
        Aug 10 at 7:21










      • @It'scominghome One scenario would be if you want to publish it as part of an API or library and make sure that users of it don't change it accidentally.
        – memo
        Aug 10 at 7:23






      • 1




        @memo very ugly and may introduce undefined behavior.
        – tilz0R
        Aug 10 at 7:25






      • 1




        @tilz0R I just answered the question, not that I would recommend it
        – memo
        Aug 10 at 7:27
















      • Yes, But that way I myself can't modify y.
        – Raman
        Aug 10 at 7:19










      • Yes, you can if you cast it back! ((struct s1 *) (o->y))->b=30;
        – memo
        Aug 10 at 7:21










      • @It'scominghome One scenario would be if you want to publish it as part of an API or library and make sure that users of it don't change it accidentally.
        – memo
        Aug 10 at 7:23






      • 1




        @memo very ugly and may introduce undefined behavior.
        – tilz0R
        Aug 10 at 7:25






      • 1




        @tilz0R I just answered the question, not that I would recommend it
        – memo
        Aug 10 at 7:27















      Yes, But that way I myself can't modify y.
      – Raman
      Aug 10 at 7:19




      Yes, But that way I myself can't modify y.
      – Raman
      Aug 10 at 7:19












      Yes, you can if you cast it back! ((struct s1 *) (o->y))->b=30;
      – memo
      Aug 10 at 7:21




      Yes, you can if you cast it back! ((struct s1 *) (o->y))->b=30;
      – memo
      Aug 10 at 7:21












      @It'scominghome One scenario would be if you want to publish it as part of an API or library and make sure that users of it don't change it accidentally.
      – memo
      Aug 10 at 7:23




      @It'scominghome One scenario would be if you want to publish it as part of an API or library and make sure that users of it don't change it accidentally.
      – memo
      Aug 10 at 7:23




      1




      1




      @memo very ugly and may introduce undefined behavior.
      – tilz0R
      Aug 10 at 7:25




      @memo very ugly and may introduce undefined behavior.
      – tilz0R
      Aug 10 at 7:25




      1




      1




      @tilz0R I just answered the question, not that I would recommend it
      – memo
      Aug 10 at 7:27




      @tilz0R I just answered the question, not that I would recommend it
      – memo
      Aug 10 at 7:27










      up vote
      0
      down vote













      I would write another function that takes in a const struct s1 * to modify the values of s1.






      share|improve this answer
























        up vote
        0
        down vote













        I would write another function that takes in a const struct s1 * to modify the values of s1.






        share|improve this answer






















          up vote
          0
          down vote










          up vote
          0
          down vote









          I would write another function that takes in a const struct s1 * to modify the values of s1.






          share|improve this answer












          I would write another function that takes in a const struct s1 * to modify the values of s1.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Aug 10 at 7:36









          George Wu

          261




          261




















              up vote
              0
              down vote













              In f(), const struct s2 *o means in the struct s2 being pointed to by o, the values of its members ie, x and y cannot be changed.



              With o->y->a=20, you are not modifying the value of y. You are just using that address to modify a member of the structure being pointed to by y and y's value, which is an address, remains the same.



              So those 2 lines will give no error.



              I could see no way to avoid this unless you could make the struct s2 definition to



              struct s2 
              int x;
              const struct s1 *y;
              ;


              in which case y is a pointer to a constant struct s1.



              See the spiral rule and visit the cdecl website.






              share|improve this answer
























                up vote
                0
                down vote













                In f(), const struct s2 *o means in the struct s2 being pointed to by o, the values of its members ie, x and y cannot be changed.



                With o->y->a=20, you are not modifying the value of y. You are just using that address to modify a member of the structure being pointed to by y and y's value, which is an address, remains the same.



                So those 2 lines will give no error.



                I could see no way to avoid this unless you could make the struct s2 definition to



                struct s2 
                int x;
                const struct s1 *y;
                ;


                in which case y is a pointer to a constant struct s1.



                See the spiral rule and visit the cdecl website.






                share|improve this answer






















                  up vote
                  0
                  down vote










                  up vote
                  0
                  down vote









                  In f(), const struct s2 *o means in the struct s2 being pointed to by o, the values of its members ie, x and y cannot be changed.



                  With o->y->a=20, you are not modifying the value of y. You are just using that address to modify a member of the structure being pointed to by y and y's value, which is an address, remains the same.



                  So those 2 lines will give no error.



                  I could see no way to avoid this unless you could make the struct s2 definition to



                  struct s2 
                  int x;
                  const struct s1 *y;
                  ;


                  in which case y is a pointer to a constant struct s1.



                  See the spiral rule and visit the cdecl website.






                  share|improve this answer












                  In f(), const struct s2 *o means in the struct s2 being pointed to by o, the values of its members ie, x and y cannot be changed.



                  With o->y->a=20, you are not modifying the value of y. You are just using that address to modify a member of the structure being pointed to by y and y's value, which is an address, remains the same.



                  So those 2 lines will give no error.



                  I could see no way to avoid this unless you could make the struct s2 definition to



                  struct s2 
                  int x;
                  const struct s1 *y;
                  ;


                  in which case y is a pointer to a constant struct s1.



                  See the spiral rule and visit the cdecl website.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Aug 10 at 7:38









                  J...S

                  3,2921929




                  3,2921929



























                       

                      draft saved


                      draft discarded















































                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f51780954%2fpointer-to-a-const-structure-can-members-still-be-modified%23new-answer', 'question_page');

                      );

                      Post as a guest













































































                      Comments

                      Popular posts from this blog

                      Long meetings (6-7 hours a day): Being “babysat” by supervisor

                      Is the Concept of Multiple Fantasy Races Scientifically Flawed? [closed]

                      Confectionery