我有一个结构,我想通过一些回调函数传递给一些外部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);
}
Run Code Online (Sandbox Code Playgroud)
那么,我如何改进我的代码设计,以便他们不能修改我通过的结构?
要正确处理这种情况,您只能使用前向声明来隐藏成员以及getter和setter函数.
关注下面的代码并检查:
struct s1
只有前向声明,所以你可以在其中指向它struct s2
.struct s1
是mylib.c
因此,所有成员只能到库中可见,而不是用户.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 */
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
当然,请确保->y
没有NULL
或您有未定义的行为.
您可以像这样更改第二个结构声明:
struct s2 {
int x;
struct s1 const *y;
};
Run Code Online (Sandbox Code Playgroud)
添加的const
确保 y 是只读的。
你不能.即使你传递了struct s2
by值,你也会在函数中得到一个指向非const的指针struct s1
,因为它是根据它的定义s2
包含的内容.
一旦你有一个指向非const对象的指针,你就可以改变那个对象.我在这里的意思和其他答案的意思是,它不是一个语言问题 - 更确切地说,语言在这里对你没有任何意义 - 而是一个设计问题.如果由于任何原因不能接受struct s1
可以f
从那时改变,那么你必须找到一个不同的设计,你不会将非const指针传递给它,不管它是const结构的成员.这里一个简单的方法是传递个人成员:
void f(int x, const struct s1 *y) {
y->a = 20; // error
}
Run Code Online (Sandbox Code Playgroud)
它可能不是你所期望的,但它是我能说的最好的C语言.
归档时间: |
|
查看次数: |
1556 次 |
最近记录: |