【问题标题】:Passing char array to struct member将字符数组传递给结构成员
【发布时间】:2009-09-21 15:35:37
【问题描述】:

我有以下结构:

struct hashItem {
    char userid[8];
    char name[30];
    struct hashItem *next;
};

在下面的函数中,我采用我希望分配给结构的 char 指针(char 数组)参数。

void insertItem(struct hashItem *htable[], char *userid, char *name)
{
    int hcode = hashCode(userid);
    struct hashItem *current = htable[hcode];

    struct hashItem *newItem = (struct hashItem*) malloc(sizeof(struct hashItem));
    newItem->userid = userid;
    newItem->name = name;
    [...]
}

相反,我收到以下错误:

hashtable.c: In function ‘insertItem’:
hashtable.c:62: error: incompatible types in assignment
hashtable.c:63: error: incompatible types in assignment

第 62 和 63 行是 `newItem->..." 行。

【问题讨论】:

    标签: c struct


    【解决方案1】:

    您几乎肯定不想只将 char* 分配给 char[] - 正如编译器指出的那样,类型不兼容,语义也不是您想的那样。我假设您希望结构成员包含两个 char* 字符串的值 - 在这种情况下,您需要调用 strncpy。

    strncpy(target, source, max_chars);
    

    【讨论】:

    • 假设我在代码中的其他地方确定 char 数组的长度小于给定的 8/30 字节,我将如何直接分配而不复制它?
    • 在这种情况下,您将在结构中使用 char*,然后将指针复制过去。 char* 只是指向某些包含字符的内存的指针。 char[] 是用于 n 个字符的固定长度存储分配。您不能以合理的方式在它们之间进行分配。
    • @Christian:确保长度与您分配或复制无关。您永远不能分配给 C 中的数组。语言不允许。您必须决定是否希望新的 hashItem 包含传递给 insertItem 的字符串的副本(在这种情况下使用某种副本,以及某种边界检查),还是指向它的指针(在这种情况下使用char* 而不是结构中的 char[])。
    【解决方案2】:

    你应该改变你的结构

    struct hashItem {
      char userid[8];
      char *name;
      struct hashItem *next;
    };
    

    分配一个字符指针到一个名字。在您定义的结构中 char name[30] 只是 30 个字符。

    【讨论】:

    • 当然假设 insertItem 的调用者将保证名称字符串在 hashItem 对象的生命周期内保持有效。
    【解决方案3】:

    您不能像您尝试的那样将指向字符串的指针分配给字符数组。相反,您需要使用亚当指示的 strncpy 复制字符串的内容:

    strncpy (newItem->userid, userid, 8);
    

    当你声明一个包含字符数组的结构体时,你是在结构体内部分配内存来存储给定长度的字符串。

    当您将指针传递给您的函数时,您传递的是一个内存地址(一个整数),该地址指示可以找到以空字符结尾的字符串的位置。

    将指针分配给数组没有意义。该数组已经为它分配了内存——不能让它“指向”另一个位置。

    虽然您可以在结构中使用指针,但您需要非常小心,在分配它们时,您是在告诉它们指向在您将使用该结构的时间段内有效的东西。例如,这段代码很糟糕,因为在fillStructure 返回后,传递给insertItem 的字符串不再存在:

    struct hashItem
    {
       char * userid;
    };
    
    void insertItem (struct hashItem * item, char * userid)
    {
       item->userid = userid;
    }
    
    void fillStructure (struct hashItem * item)
    {
       const char string[] = "testing";
       insertItem (item, string);
    }
    
    int main(void)
    {
       struct hashItem item;
       fillStructure (&item);
       /* item->userid is now a dangling pointer! */
    }
    

    如需更多信息,我建议阅读 C 常见问题解答的“数组和指针”一章——从 Question 6.2 开始并继续阅读。

    【讨论】:

    • 在此处插入有关 strncpy 的常用参数:如果传入的用户 ID 正好是 8 个字符长,那么此代码将导致存储的字符串不被 nul 终止。这可能不是你想要的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-06
    • 2021-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多