Sam*_*Lou 37 c const c99 compiler-warnings
我在尝试制作常量正确的代码时偶然发现了一个小问题.
我本来想写一个函数,它接受一个const结构的指针,告诉编译器"请告诉我,如果我正在修改结构,因为我真的不想".
我突然想到编译器会允许我这样做:
struct A
{
char *ptrChar;
};
void f(const struct A *ptrA)
{
ptrA->ptrChar[0] = 'A'; // NOT DESIRED!!
}
Run Code Online (Sandbox Code Playgroud)
这是可以理解的,因为实际上const是指针本身,而不是它指向的类型.我想让编译器告诉我,我正在做一些我不想做的事情,但是,如果可能的话.
我使用gcc作为我的编译器.虽然我知道上面的代码应该是合法的,但我仍然检查它是否会发出警告,但没有任何结果.我的命令行是:
gcc -std=c99 -Wall -Wextra -pedantic test.c
Run Code Online (Sandbox Code Playgroud)
有可能解决这个问题吗?
Lun*_*din 19
如果需要,一种设计方法的方法是对同一对象使用两种不同的类型:一种读/写类型和一种只读类型.
typedef struct
{
char *ptrChar;
} A_rw;
typedef struct
{
const char* ptrChar;
} A_ro;
typedef union
{
A_rw rw;
A_ro ro;
} A;
Run Code Online (Sandbox Code Playgroud)
如果函数需要修改对象,则将读写类型作为参数,否则采用只读类型.
void modify (A_rw* a)
{
a->ptrChar[0] = 'A';
}
void print (const A_ro* a)
{
puts(a->ptrChar);
}
Run Code Online (Sandbox Code Playgroud)
为了使调用者界面更加一致并使其保持一致,您可以使用包装器函数作为ADT的公共接口:
inline void A_modify (A* a)
{
modify(&a->rw);
}
inline void A_print (const A* a)
{
print(&a->ro);
}
Run Code Online (Sandbox Code Playgroud)
使用此方法,A现在可以实现为opaque类型,以隐藏调用者的实现.
这是一个实现与接口或"信息隐藏" - 或者说非隐藏;-)-问题的示例.在C++中,只需将指针设为私有,并定义合适的公共const访问器.或者可以使用访问者定义抽象类 - "接口".正确的结构将实现这一点.不需要创建结构实例的用户只需要查看该接口.
在C中,可以通过定义一个函数来模拟它,该函数将指向struct的指针作为参数并返回指向const char的指针.对于不创建这些结构实例的用户,甚至可以提供一个"用户头",它不会泄漏结构的实现,而只是定义操纵函数(或返回,如工厂)指针.这使结构保持不完整的类型(因此只能使用指向实例的指针).这种模式有效地模拟了C++在幕后使用this指针所做的事情.
这是C语言的已知问题,不可避免.毕竟,您没有修改结构,const而是通过从结构中获取的非限定指针修改单独的对象.const语义最初的设计围绕着需要将内存区域标记为物理上不可写的常量,而不是围绕防御性编程的任何顾虑.
也许如果您决定使用C11,您可以实现一个Generic宏,它引用同一成员的常量或变量版本(您还应该在结构中包含一个union).像这样的东西:
struct A
{
union {
char *m_ptrChar;
const char *m_cptrChar;
} ;
};
#define ptrChar_m(a) _Generic(a, struct A *: a->m_ptrChar, \
const struct A *: a->m_cptrChar)//, \
//struct A: a.m_ptrChar, \
//const struct A: a.m_cptrChar)
void f(const struct A *ptrA)
{
ptrChar_m(ptrA) = 'A'; // NOT DESIRED!!
}
Run Code Online (Sandbox Code Playgroud)
联盟为一个成员创建了2个解释.的m_cptrChar是一个指针,指向恒定炭和m_ptrChar非恒定.然后宏根据它的参数类型决定引用哪个.
唯一的问题是宏ptrChar_m只能与这个结构的指针或对象一起工作,而不能同时工作.