一个有一个成员的结构,有时需要```,有时不需要

时间:2013-08-05 21:49:06

标签: c warnings const

我正在开发一个程序,该程序在许多地方使用通用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);
}

备注

  1. 我无法将结构的声明更改为const char* s,因为大多数指向结构的函数都会修改s
  2. 我想我可以有两个结构,一个带有char* s,另一个有const char* s,但这看起来非常难看(创建冗余,需要两个结构之间的转换功能)。
  3. 如果有人对该程序感兴趣Navit,则结构为struct attr。我为这个问题创建了一个简单的例子。

4 个答案:

答案 0 :(得分:5)

有趣的是,您似乎可以在union

中执行此操作
struct mystruct {
    int i;

    union {
        char *s;
        const char *cs;
    };
};

现在,union的规则适用:仅使用分配给的联合成员。如果函数'promises'表现出来,您可以在不发出警告的情况下将字符串分配给cs

具体来说,所做的是分配给cs,然后将结构作为非const参数传递。

答案 1 :(得分:2)

基于paddy和jxh的想法,我提出了一个看起来很实用的解决方案:

  • 使用const char*成员
  • 创建结构的“const版本”
  • 使用union
  • 将其与结构的“非const”版本相结合

代码:

typedef struct const_mystruct {
    int i;
    const char * s;
} const_mystruct;

typedef union {
    struct {
        int i;
        char *s;
    };
    const const_mystruct cms;
} mystruct;

这实现了以下目标(类似于const限定符对简单指针的作用):

  • 如果函数允许不修改char数组,函数可以接受const_mystruct*,编译器会强制执行此操作。
  • mystruct适用于需要修改char数组的情况/ free() d。
  • 最后,通过阅读mystructconst_mystruct可以转换为mystruct.cms。 (潜在危险的)转化const_mystruct - &gt; mystruct编写mystruct.cms是不可能的,因为mystruct.cmsconst,因此无法写入。

说明使用的代码:

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