我正在开发一个程序,该程序在许多地方使用通用struct
来绕过相关值。该结构包含一个字段char* s
。
许多功能修改s
;但是,有时结构用于将信息传递给只读取它的函数。在这些情况下,用于初始化s
的字符串通常是const char*
。但是,将其分配给s
会导致编译器警告。
虽然技术上正确,但此警告感觉不对,因为该功能不会修改s
。
有没有办法绕过这个警告,除了扔掉const?有没有办法让函数承诺它会将结构成员视为const
?
示例:
#include <stdio.h>
struct mystruct{
int i;
char* s;
};
void i_only_read(const struct mystruct *m){
printf("mystruct: i=%d, s=%s\n", m->i, m->s);
}
int main(int argc, char **argv){
const char* cstr = "Hello";
struct mystruct m;
m.i=99;
/* gcc warning: assignment discards ‘const’ qualifier
* from pointer target type
*/
m.s=cstr;
i_only_read(&m);
}
备注
const char* s
,因为大多数指向结构的函数都会修改s
。char* s
,另一个有const char* s
,但这看起来非常难看(创建冗余,需要两个结构之间的转换功能)。struct attr
。我为这个问题创建了一个简单的例子。答案 0 :(得分:5)
有趣的是,您似乎可以在union
:
struct mystruct {
int i;
union {
char *s;
const char *cs;
};
};
现在,union
的规则适用:仅使用分配给的联合成员。如果函数'promises'表现出来,您可以在不发出警告的情况下将字符串分配给cs
。
具体来说,不所做的是分配给cs
,然后将结构作为非const参数传递。
答案 1 :(得分:2)
基于paddy和jxh的想法,我提出了一个看起来很实用的解决方案:
const char*
成员代码:
typedef struct const_mystruct {
int i;
const char * s;
} const_mystruct;
typedef union {
struct {
int i;
char *s;
};
const const_mystruct cms;
} mystruct;
这实现了以下目标(类似于const
限定符对简单指针的作用):
const_mystruct*
,编译器会强制执行此操作。mystruct
适用于需要修改char数组的情况/ free()
d。mystruct
,const_mystruct
可以转换为mystruct.cms
。
(潜在危险的)转化const_mystruct
- &gt; mystruct
编写mystruct.cms
是不可能的,因为mystruct.cms
是const
,因此无法写入。说明使用的代码:
#include <stdio.h>
#include <malloc.h>
/* [structs omitted] */
void i_only_read(const const_mystruct *m){
printf("mystruct: i=%d, s=%s\n", m->i, m->s);
}
void i_might_modify(mystruct *m){
printf("noconst: mystruct: i=%d, s=%s\n", m->i, m->s);
}
int main(void){
const char* cstr = "Hello";
const_mystruct cm;
cm.i=99;
cm.s=cstr;
// Method promises not to change the structure: OK.
i_only_read(&cm);
// Pass a "constant" structure into a method that might modify it:
// diagnosed by compiler (warning or error).
i_might_modify(&cm);
// Trying to remove "const" from the pointer: compiler will not allow this...
// m.cms.s=cstr;
mystruct m;
m.i=99;
m.s=malloc(10);
// Struct is not "const", so modification is OK.
i_might_modify(&m);
// Convert to "const" struct, without cast.
i_only_read(&(m.cms));
return 0;
}
这为使用const
指针提供了相同的保证,这是我的目标(类似于“递归const”)。
潜在问题:
struct
的两个版本感觉很笨。我会看看我是否真的可以使用它......
答案 2 :(得分:1)
这个解决方案有点复杂。它结合了@ paddy对union
的建议,允许const char *
分配给union
- {if}版本的数据结构上的另一个const
,以提供严格的执行。
typedef struct const_mystruct {
const int i;
const char * const s;
} const_mystruct;
typedef union {
struct {
int i;
union {
char *s;
const char *cs;
};
};
const_mystruct cms;
} mystruct;
void i_only_read(const_mystruct *m){
printf("mystruct: i=%d, s=%s\n", m->i, m->s);
}
int main(int argc, char **argv){
const char* cstr = "Hello";
mystruct m;
m.i=99;
m.cs=cstr;
i_only_read(&m.cms);
}
答案 3 :(得分:0)
我意识到这个答案是你的问题试图避免的。但是,如果没有使用gcc以外的编译器或将代码转换为不可读性,那么有时候代码中的规范方法和注释很少会解决问题!
以下代码片段中const
的用途是什么?
void i_only_read(const struct mystruct *m){
printf("mystruct: i=%d, s=%s\n", m->i, m->s);
}
从C的角度来看,它暗示该函数不会修改mystruct
。如果这个定义以某种方式给出gcc
拟合,那么删除const
verbage并在代码中强制执行“do not update”透视。
// the programmer can/must only read mystruct
void i_only_read(struct mystruct *m){
printf("mystruct: i=%d, s=%s\n", m->i, m->s);
}