【问题标题】:C - Pointers and MemoryC - 指针和内存
【发布时间】:2013-04-11 15:06:58
【问题描述】:

我有点困惑,在这个示例代码中说;

ptrMem = createSharedMemory();  

ptrTemp = ptrMem;

ptrMem 指向由SHMGET 创建的共享内存位置

ptrTemp 也指向它有什么意义,我如何同时利用这两者?

我想遍历内存并分配随机数,例如;

ptrTemp = ptrMem;       
for(nCount = 0; nCount < 24; nCount++)
        {   
            x = rand() % 10000;
            *ptrTemp++ = x;
        }   

这种情况是有一个客户端和一个服务器通过共享内存进行通信。需要有一个字符或类似的东西向其他进程表明他们可以进行处理。例如,在上述循环完成后; *ptrMem='*'.

【问题讨论】:

  • 用于处理分配的内存的其他内存,以便稍后在代码中释放。
  • 取决于代码的其余部分,例如你可以增加一个来遍历内存
  • 您可能会这样做的原因有很多。你能补充更多信息吗?
  • 所以比如我想循环内存并添加随机整数; ptrTemp = ptrMem; x = rand() % 10000; *ptrTemp++ = x;。为什么我要在这里使用ptrTemp 而不是ptrMem

标签: c arrays pointers memory


【解决方案1】:

这是因为在循环中您更改指针ptrTemp。做ptrTemp++后指针不再指向原来的内存。

【讨论】:

    【解决方案2】:
    • 让 ptrTemp 也指向它有什么意义?如何同时使用两者?

    这与链表中的“头”指针相同。

    ptrTemp = ptrMem;     // here both pointers point to the start
                          //  of your shared memory location
    

    当你运行你的循环时,你会一次又一次地执行这个:

    *ptrTemp++ = x;
    

    现在ptrTemp 不再指向您的共享内存位置的开始。在这个具体的例子中,你知道你循环了 24 次(你的指针增加了 24 次),所以你可以使用指针算术并“回退”地址,但为什么要麻烦呢?对于一些额外的字节,您可以只使用一个新指针,并且始终可以方便地引用缓冲区的开头,这很可能需要传递/引用。

    请记住,ptrTemp 的名称中包含“Temp”,表示它用于某种临时存储。


    编辑: * 运算符用于取消引用指针(或声明它)。所以在你的代码中:

    ptrTemp = ptrMem; // Assigning one pointer to another, no need for the * here since
                      // they are both pointers.
    
    *ptrTemp++ = x; // here you are assigning a value to the memory pointed to by ptrTemp
                    // to assign a value you need to dereference, then we increment ptrTemp
    
    • 如果我想打印内存,我必须这样做; ptrTemp = ptrMem,对吧?

    并非如此,这只会将临时指针设置回共享内存缓冲区的开头。如果你想打印出内存的内容,你可以简单地这样做:

    for(nCount = 0; nCount < 24; nCount++)
        printf("%p: %d\n", ptrMem+nCount, *(ptrMem+nCount));
    

    这不会改变 ptrMem 所指出的内容(因为我们从不覆盖它)我们想知道哪个内存地址 (ptrMem+nCount) 具有什么值(它的取消引用版本)所以我们打印一个 "%p" (指针格式字符串)和一个"%d"(整数格式字符串)

    【讨论】:

    • 好吧好吧,我明白了!你介意再为我解释一个细节吗?在循环之前,我在循环中执行ptrTemp = ptrMem(没有星号); *ptrTemp++(注意星号)然后,如果我想打印内存,我必须这样做; ptrTemp = ptrMem,对吧?但是为什么这里不需要星号呢?
    • @TomSothcott - 该编辑是否有助于澄清您的其他问题?
    【解决方案3】:

    如果我需要更改他的值以访问共享内存的不同内存区域,我会使用prtTemp

    如果我需要指向共享内存区域的第一个字节,我可以使用未触及的ptrMem

    【讨论】:

      【解决方案4】:

      这是一个品味问题。

      如果你想通过增加一个指针来遍历内存,那么你需要保持一个指向开头的指针,以便它可以被正确地释放。

      您也可以使用索引来遍历内存而不使用临时指针。

      for(nCount = 0; nCount < 24; nCount++)
      {   
          x = rand() % 10000;
          ptrMem[nCount] = x;
      } 
      

      在使用指针迭代内存缓冲区而不是仅使用索引时,我见过(或自己做过)的大多数情况是指针前进的量不一致。例如,如果您的缓冲区在每个元素中始终具有相同的数据类型,则编译器可以知道要为您增加多少指针(或计算索引偏移量)。

      struct mystruct* ptrMem;
      ptrMem[0]; // first element
      ptrMem[1]; // second element
      
      struct mystruct* ptrTemp = ptrMem;
      *ptrTemp; // first element
      ptrTemp++; // increments ptrTemp by sizeof(struct mystruct) bytes
      *ptrTemp; // second element
      

      在这种情况下,您希望使用哪一个是个人喜好问题。

      例如,如果编译器无法知道缓冲区中包含的数据的结构,例如处理命令长度可变的 midi 文件,则将指针迭代一个字节会更容易(更易读)一次。不过,编译器知道字节的大小,因此您也可以在这里使用索引。

      【讨论】:

        猜你喜欢
        • 2012-03-27
        • 2021-11-29
        • 2013-10-31
        • 2015-12-15
        • 1970-01-01
        • 2016-03-06
        • 1970-01-01
        • 2014-02-14
        相关资源
        最近更新 更多