寻找一种优雅的方式来在C中声明带有字符串的struct数组

时间:2017-05-20 15:41:13

标签: c arrays string coding-style

我正在尝试做一些类似我在C ++中使用QT所做的事情,在C. 这是C ++代码的一部分:

typedef struct {
    int     order;
    int     type;
    QString cmd;
    QString res[2];
    double  timeout;
    int     exitAfterNChar;
}atCmdList_t;
atCmdList_t atCmdList[] = {
    {0,0, "ATI", {"", ""}, 1, -1},
    {0,0, "AT+GSN", {"", ""}, 1, -1},
    {0,0, "AT+COPS?", {"+COPS: 0,0,\"vodafone IT\",2", ""}, 1, -1}
};

我正试图在C中做类似的事情。 我知道我可以做这样的事情:

const char s_00[]  = {""};
const char s_01[]  = {"ATI"};
const char s_02[]  = {"AT+GSN"};
const char s_03[]  = {"AT+COPS?"};

typedef struct {
    int     order;
    int     type;
    const char *  cmd;
    const char *  res[2];
    double  timeout;
    int     exitAfterNChar;
} atCmdList_t;
atCmdList_t atCmdList[] = {
    {0,0, s_01, {s_00, s_00}, 1, -1},
    {0,0, s_02, {s_00, s_00}, 1, -1},
    ....
};

但这并不像C ++那样优雅和清晰。 我的“使命”是创建或查找预编译器宏,使代码尽可能可读。

有什么建议吗?

1 个答案:

答案 0 :(得分:0)

您当前的C代码是错误的,因为&s_00不是指向const-char(const char*)的指针,而是指针指向const-char的指针(const char**),因为s_00的类型为const char[]。其他人也一样。所以必须先修复它才能使它看起来整洁。

此外,您将const投放到了只有“安全”的地方。如果你知道指向内存的话毕竟不会被修改。如果你不需要修改你的AT命令/ repsonse,那么它们实际上是有效的,所以你可以简单地将const char*用于相关的struct成员并在任何地方使用文字。到目前为止最简单的解决方案,您的代码将如下所示:

typedef struct {
  int     order;
  int     type;
  const char* cmd;
  const char* res[2];
  double  timeout;
  int     exitAfterNChar;
} atCmdList_t;

atCmdList_t atCmdList[] = {
  {0,0, "ATI", {"", ""}, 1, -1},
  {0,0, "AT+GSN", {"", ""}, 1, -1},
  {0,0, "AT+COPS?", {"+COPS: 0,0,\"vodafone IT\",2", ""}, 1, -1}
};

如果你需要修改它们(那么你的C ++代码可能也没有正常工作),你需要做一些涉及:

    首先
  1. malloc() / calloc()适当的内存量
  2. strncpy() const char* literall到新分配的struct成员内存
  3. 完成后,请确保再次free()该内存。
  4. 举例说明如何实施:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    struct Foo 
    {
      char * data;
    };
    
    char * copy_static_string(const char* src, size_t sz) 
    {
      if(src) 
      {
        char * dst = malloc(sz);
        return dst ? strncpy(dst, src, sz) : NULL;
      }
      else 
      {
        return NULL;
      }
    }
    
    #define COPY_STATIC_STRING(x) (copy_static_string((x), sizeof(x)))
    
    int main()
    {
      struct Foo foo = { .data = COPY_STATIC_STRING("hello, world!") };
      printf("%s\n", foo.data); // check .data != NULL, don't forget!
      free(foo.data); // don't forget to clean up, either!
      return 0;
    }
    

    顺便说一下:你的C ++代码工作的原因&#39;是QString是一个具有写时复制语义(分离)的容器,因此您可以安全地传递它const char*,QString将在需要时复制它。 (因此不会尝试写入原始const char*)。