指向const结构的指针,仍然可以修改成员吗?

时间:2018-08-10 07:12:16

标签: c

我有一个结构,我想通过一些回调函数传递给一些外部C代码,这些函数在我的程序中注册。但是,我想将该结构作为只读传递。我担心的是,它们仍然可以在我传递的原始结构中修改指向我的指针的结构。用下面的小例子解释:

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);
}

那么,如何改进我的代码设计,以使他们无法修改我通过的结构?

5 个答案:

答案 0 :(得分:9)

要正确处理这种情况,您只能使用前向声明将成员与getter和setter函数一起隐藏。

关注下面的代码并检查:

  • struct s1仅具有 forward声明,因此您可以在struct s2中指向它。
  • struct s1的实际实现位于mylib.c中,因此所有成员仅对您的库可见,而对用户不可见。
  • Getters和Setters的实现是为了设置/读取这些隐藏成员的值,因为只有您的图书馆才有权访问这些成员,从而使其对用户完全隐藏。
  • 这迫使他使用您的功能。

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: %d\r\n", a);

  return 0;
}

当然,请确保->y不是NULL或您的行为不确定。

答案 1 :(得分:5)

您不能。即使您按值传递struct s2,您也将在函数中获得指向非const struct s1的指针,这仅仅是因为s2根据其定义包含了

一旦有了指向非const对象的指针,就可以更改该对象。我在这里的意思以及其他答案的意思是,这不是语言问题-更确切的说,这里的语言对您没有帮助-而是设计问题。如果出于某种原因不能将struct s1更改为f,那么您必须找到一个不向其传递非const指针的其他设计,无论它是const的成员结构与否。一种简单的方法是传递各个成员:

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

可能不是您所期望的,但这是我能用C语言说的最好的话。

答案 2 :(得分:4)

您可以像这样更改第二个struct声明:

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

添加的const确保y为只读。

答案 3 :(得分:0)

我将编写另一个函数,该函数采用const结构s1 *来修改s1的值。

答案 4 :(得分:0)

f()中,const struct s2 *o表示struct s2指向o时,其成员的值即x和{{1} }无法更改。

对于y,您没有修改o->y->a=20的值。您只是使用该地址来修改y所指向的结构的成员,而y的值(即地址)保持不变。

所以这两行不会出错。

除非您可以将y定义为

,否则我无法避免这种情况。
struct s2

在这种情况下,struct s2 { int x; const struct s1 *y; }; 是指向常量y的指针。

查看spiral rule并访问cdecl网站。