【问题标题】:Invalid lvalue in assignment error when trying to make a pointer NULL尝试使指针为 NULL 时,赋值错误中的左值无效
【发布时间】:2010-03-07 22:09:21
【问题描述】:

我有一个我制作的结构类型的指针。在程序启动时,它以 NULL 开始,然后我需要 malloc/realloc,因为我需要添加/删除这些结构,我只是要使用我的指针指向第一个结构并像数组一样移动它。

当我 malloc/realloc 时,我总是使内存中“数组”/区域的大小比它需要的大一。我这样做是为了可以将内存中的“最后一个索引”/区域设置为 NULL,这样我就可以说类似 while(指针!= NULL)的内容。

我收到错误:当我尝试使用以下行将 NULL 分配给内存数组/区域中的最后一个位置时,分配中的左值无效:

  // Realloc remotelist by adding one to connrhosts
  connrhosts++;
  remotelist = realloc(remotelist, sizeof(rhost)*(connrhosts + 1));
  (remotelist + connrhosts) = NULL;

我想我说的是:

  • 是时候向我的数组添加一个新结构了,所以我会将 connrhosts 增加一个。
  • 将指向 remotelist 的内存重新分配到一个新的内存区域,该区域是 connrhosts 的大小(我将使用多少个结构)以及一个额外的空间,以便我可以将其设为 NULL
  • 将远程列表指向新的内存区域
  • 使用我的指针 remotelist 并添加偏移量 connrhosts 现在将指向内存区域的最后一个索引并使该指针为 NULL。

据我所知(或感觉)我所做的一切都是正确的,但我一直在从事这个项目一段时间,并且我的印象是我有狭隘的眼光。我希望有一双新的眼睛来看看我的逻辑/代码,让我知道他们的想法和我做错了什么。再次感谢。 :D

编辑 - 我的部分问题是我认为我对指针可以做什么有误解。

这是我的结构:

typedef struct {
  char address[128]; // Buffer that holds our address of the remote host
  int port; // Port of the remote host
  int conn; // FD to the connection of our remote host
  int ofiles; // Open files associated with the remote host
} rhost;

我希望我能做的是循环遍历我的数组/内存区域,并说如果它不为 NULL,然后用它做点什么。所以我原来的循环语句是 while (NULL != remotelist)。现在我相信正在阅读响应和 cmets,因为我正在检查指针是否为空,所以这个逻辑是错误的?我应该检查指针指向的内存/结构区域是否为空?如果是这种情况,它应该类似于 while (NULL != *(remotelist + someoffset))?

我这样做是因为我的老师建议/在课堂上谈论它。

我对 remotelist 的初始声明/初始化是:rhost *remotelist = NULL;

【问题讨论】:

  • 顺便说一句,你为什么在分配++connrhosts 然后使用connrhosts + 1?那个额外的+ 1 的目的是什么?
  • connrhosts 是我目前可以连接的远程主机数量。因此,在我的数组中,如果它是两个并且我没有执行 connrhosts + 1,我将只有两个索引,0 和 1,并且都将指向一个结构。我做了 + 1,所以我可以有三个索引,0、1 和 2,其中 0 和 1 指向一个结构,2 可以等于 NULL。这样我就可以有像 while (NULL != remotelist) 之类的语句
  • rhost 是一个结构体。 remotelist 指向的分配是这些结构的数组,而不是指针数组。您不能将结构设置为 NULL,因此您需要另一种方式来表示列表的结束。一种方法是让整数与计数保持一致,并将其与指针一起传递。另一种方法是使用 rhost 的一个字段作为“数据结束”标记,例如,如果 ofiles 为 -1,则表示数组结束。您可以使用实际的以 NULL 结尾的指针数组。我不建议这样做:您必须单独分配它们。
  • 如果我说类似 rhost **remotelist;然后 remotelist = realloc(remotelist, sizeof(*rhost)*(connrhosts + 1));那么我可以将这些指针设置为 NULL 吗?
  • 你会的,但给你的只是一个指针数组。然后,您可以分别分配一些 rhost 对象。不过是sizeof(rhost*),或者sizeof(*remotelist),而不是sizeof(*rhost)

标签: c compiler-construction pointers compiler-errors


【解决方案1】:

当 LHS 是一个未成为可赋值变量的计算表达式时,会发生错误的左值赋值。你正在做的看起来像是应该在 RHS 上的操作(指针算术)。

你可以做的是:

remotelist[connrhosts] = NULL;  // array notation asuming 
                                // remotelist is an array of pointers

假设 connrhosts 是 intsize_t 或者你可以这样做:

remotelist += connrhost; // pointer arithmetic
*remotelist = NULL; // assuming remotelist is an array of pointers.

【讨论】:

  • 不会远程列表 += connrhost; // 指针运算 *remotelist = NULL;实际上改变了我的指针指向的地址?如果是这样,那对我来说将是一个问题。我正在添加偏移量或 connrhosts,所以我可以说“远离开头的这么多点使 NULL”。我还提供了更多关于我的结构和我认为我在做什么的文档。
  • 是的,确实如此,它通过远程列表类型的 connrhost 块递增指针。之后您必须再次将其移回。为了完整性,我包括了这两个选项。我给下面的答案 +1 表明 [] 表示法更干净 - 它是。
  • 我继续尝试使用 [] 表示法,但随后我在分配错误中遇到了不兼容的类型。所以我一定是之前做错了什么,或者我真的不知道我在做什么?
  • 听起来你的类型搞砸了,但看看史蒂夫杰索普对你的问题的评论。听起来您正在尝试模拟以 \0 字符结尾的字符串。这实际上等于 0,所以如果有意义,最后一个 int 是 0,这与 NULL 不同,NULL 是一个 void *,什么都没有。
【解决方案2】:

您还需要取消引用您的指针。

*(remotelist + connrhosts) = NULL;

虽然我觉得

 remotelist[connrhosts] = NULL; 

更清晰。

【讨论】:

    【解决方案3】:

    您需要使用* 取消对指针的引用,以访问指针所寻址的内存中存储的内容。

    *(remotelist + connrhosts) = NULL;
    

    【讨论】:

      【解决方案4】:

      表达式pointer != NULL 指的是指针本身,而不是指针所引用的内存。即使你可以给它赋值NULL,也解决不了问题。

      增加指针后,它不是NULL,它有一个地址,你最后一个额外的结构槽的地址。

      我想,您可以通过以下方式将此区域设置为 0:

      memset(remotelist + connrhosts, 0, sizeof(rhost));
      

      如果这个字段在真正的结构上永远不会为 0,那么你可以执行类似 p->field == 0 的操作...

      就我个人而言,如果我理解正确的话,我会处理这个问题,方法是分配第二个指向结构的指针数组,或者只跟踪我有多少,或者很可能通过使用这样的集合作为链表或树,也就是比realloc().更优雅的扩展操作

      【讨论】:

        【解决方案5】:

        “内存/结构区域”无法分配NULL,也无法与NULL 进行比较。 NULL 仅与指针一起使用。

        如果您想设置 [新分配的] 结构的所有字段为零,在 C89/90 中,常见的习惯用法是在 = { 0 } 初始化程序的帮助下完成:

        const rhost ZERO_HOST = { 0 };
        ...
        connrhosts++; 
        remotelist = realloc(remotelist, connrhosts * sizeof *remotelist); 
        remotelist[connrhosts] = ZERO_HOST; 
        

        或者你可以简单地使用memset(这是一个hack)。

        至于检查数组中的条目是否全零......虽然memcmp函数可以提供帮助,但没有内置操作

        if (memcmp(&remotelist[i], &ZERO_HOST, sizeof ZERO_HOST) == 0)
          /* All zeroes */;
        

        (这也是一种 hack,尽管不像 memset 那样“hackish”)。

        但通常不会那样做。这样做真的没有意义。通常,您应该只选择结构中的一个字段(“主要”字段),它可以告诉您结构是否“已使用:”并将该单个字段与 0 进行比较

        if (remotelist[i].address[0] == '\0')
          /* Entry is not used */;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-04-26
          • 1970-01-01
          • 2019-12-11
          • 2016-06-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多