一种结构,其成员有时需要为'const',有时不需要为'const'
我正在开发一个程序,它在许多地方使用一个通用的一种结构,其成员有时需要为'const',有时不需要为'const',c,warnings,constants,C,Warnings,Constants,我正在开发一个程序,它在许多地方使用一个通用的struct,在相关的值之间穿梭。此结构包含一个字段char*s 许多函数修改s;但是,有时结构用于将信息传递给只读取信息的函数。在这些情况下,通常用于初始化s的字符串是const char*。但是,将其指定给s会导致编译器警告 虽然技术上正确,但此警告感觉是错误的,因为该函数不修改s。 除了扔掉常量之外,还有什么办法可以绕过这个警告吗?函数是否有办法保证将结构成员视为常量 例如: #include <stdio.h> struct m
struct
,在相关的值之间穿梭。此结构包含一个字段char*s
许多函数修改s
;但是,有时结构用于将信息传递给只读取信息的函数。在这些情况下,通常用于初始化s
的字符串是const char*
。但是,将其指定给s
会导致编译器警告
虽然技术上正确,但此警告感觉是错误的,因为该函数不修改s
。
除了扔掉常量之外,还有什么办法可以绕过这个警告吗?函数是否有办法保证将结构成员视为常量
例如:
#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);
}
#包括
结构mystruct{
int i;
char*s;
};
只读无效(const struct mystruct*m){
printf(“mystruct:i=%d,s=%s\n”,m->i,m->s);
}
int main(int argc,字符**argv){
const char*cstr=“你好”;
结构mystruct m;
m、 i=99;
/*gcc警告:分配丢弃“const”限定符
*从指针目标类型
*/
m、 s=cstr;
我只读(&m);
}
注释
const char*s
,因为大多数指向结构的函数都会修改s
char*s
,另一个是const char*s
,但这看起来非常难看(造成冗余,需要两个结构之间的转换函数)struct attr
。我为这个问题创建了一个简单的示例有趣的是,您似乎能够在
联盟中做到这一点:
struct mystruct {
int i;
union {
char *s;
const char *cs;
};
};
现在,union
的规则适用:仅使用分配给的union成员。如果函数“保证”正常运行,您可以将字符串分配给cs
,而无需发出警告
具体地说,您不应该做的是分配给cs,然后将结构作为非常量参数传递。我意识到这个答案正是您的问题试图避免的。然而,如果不使用gcc以外的编译器或将代码扭曲成不可读性,那么有时一种严格的方法和代码中很少的注释就可以解决问题
以下代码片段中的const
的目的是什么
void i_only_read(const struct mystruct *m){
printf("mystruct: i=%d, s=%s\n", m->i, m->s);
}
从C的角度来看,这意味着该函数不会修改mystruct
。如果该定义以某种方式给出了gcc
fit,则删除const
verbage并在代码中强制执行“不更新”透视图
// 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);
}
这个解决方案有点复杂。它结合了@paddy对
联合
的建议,允许常量字符*
赋值与另一个联合
在常量
化版本的数据结构上,以提供严格的执行
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);
}
基于paddy和jxh的想法,我提出了一个看起来很实用的解决方案:
- 使用
成员创建结构的“const version”const char*
- 通过使用并集将其与结构的“非常量”版本组合
const
限定符对简单指针的作用):
- 函数可以接受const_mystruct*,如果它们希望保证不修改字符数组,编译器将强制执行此操作
适用于需要修改字符数组的情况/mystruct
dfree()
- 最后,可以通过读取
将mystruct.cms
转换为mystruct
。 通过写入const\u mystruct
来转换mystruct.cms
->const\u mystruct
(潜在危险)是不可能的,因为mystruct
是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 mystruct*m){
printf(“mystruct:i=%d,s=%s\n”,m->i,m->s);
}
void i_may_modify(mystruct*m){
printf(“noconst:mystruct:i=%d,s=%s\n”,m->i,m->s);
}
内部主(空){
const char*cstr=“你好”;
const_mystruct cm;
cm.i=99;
cm.s=cstr;
//方法承诺不会更改结构:OK。
i_only_read(&cm);
//将“常量”结构传递给可能修改它的方法:
//由编译器诊断(警告或错误)。
i_可能会修改(&cm);
//试图从指针中删除“const”:编译器将不允许此操作。。。
//m.cms.s=cstr;
我的结构;
m、 i=99;
m、 s=malloc(10);
//Struct不是“const”,所以修改是可以的。
我可以修改(&m);
//转换为“const”结构,不使用强制转换。
我只读(&(m.cms));
返回0;
}
这提供了与使用const
作为指针相同的保证,这是我的目标(类似于“递归const”)
潜在问题:
- 设置似乎相当复杂,其他开发人员可能很难理解它(我当然有)
- 拥有相同结构的两个版本感觉很笨拙
我将看看我是否能真正使用这个…+1我正在实现一个通用字符串对象,它可以通过复制或不复制进行初始化,我也遇到了这个问题。我很高兴你问这个问题。@H2CO3:啊,没关系:-S@KerrekSB没问题-如果从
const char*
到(char*)
的C样式转换也是安全的,我会很高兴地使用它:)当然,1。通过联合体的类型双关是安全的,2。同一类型的合格和不合格版本保证具有相同的表示和对齐要求,因此在初始化cs
时读取s
是安全的,反之亦然。谢谢@H2CO3。
#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;
}