带有空指针的算术

时间:2020-11-02 16:13:15

标签: c pointers memory-address

我调用一个交换功能,以转移内存中的消息:

        for (int i = now->size - 1; i >= 0; i--)
        {
           void *address2 = prev->start_address + i;
           void *address1 = now->start_adress + i;

           address1 = address2;
           address2 = '\0';
        }

所以基本上我有两个地址,一个指向第一个起始位置,另一个指向第二个起始位置,必须粘贴内容。 问题是,我发现的唯一解决方案是添加int(这是i值)和prev->start_adress(这是void *),如我所示。我想正确地做,我不能将void指针更改为int。还有其他可能性吗?

我的错误:

error: invalid conversion from ‘void*’ to ‘char*’ [-fpermissive]
 warning: pointer of type ‘void *’ used in arithmetic [-Wpointer-arit]
  214 |                void *address2 = prev->start + i;
Warning: pointer of type ‘void *’ used in arithmetic [-Wpointer-arit]
  215 |                void *address1 = now->start + i;

支持信息: 我有一个链表(充满了段描述符)和一个“内存”,它是一个简单的数组[]。类似于malloc的工作原理。

typedef struct segmentdescriptor

{
   Byte allocated;
   void *start;
   size_t size;
   struct segmentdescriptor *next;
} Node;

开始指针指向数组[]中分配空间的开始。

更新: 最简单的方法是,如果您知道空指针的大小,则可以使用typecast对空指针进行算术运算:

char *address2 = (char *)prev->start + i;

如果您不知道类型,则不可能,因为例如: char *pointer指向内存的一个字节,如果您写pointer++ 到下一个字节。 int *pointer可以说是四个再见。如果您写pointer ++,则在四个字节之后进入四个字节。

下面也有很好的答案。 感谢您提供所有答案。

3 个答案:

答案 0 :(得分:2)

我不太了解 shifts a massage in memory 是什么,但是如果您只想将一个存储位置复制到另一个存储位置,则可以

  1. 使用memcpymemmove(如果内存位置重叠)

     memcpy(now->start_adress, prev->start_address, now->size);
    
  2. 编写您自己的函数以复制内存

void *mymemcpy(void *dest, const void *src, size_t size)
{
    unsigned char *cdest = (unsigned char *)dest;  //cast for C++ compiler
    const unsigned char *csrc = (unsigned char *)src;

    while(size--) *cdest++ = *csrc;
    return dest;
}
void *mymemcpy(void *dest, const void *src, size_t size)
{
    unsigned char *cdest = (unsigned char *)dest;  //cast for C++ compiler
    const unsigned char *csrc = (unsigned char *)src;

    for(size_t index = 0; index < size; index++) cdest[index] = csrc[index];
    return dest;
}
void *mymemcpy(void *dest, const void *src, size_t size)
{
    unsigned char *cdest = (unsigned char *)dest;  //cast for C++ compiler
    const unsigned char *csrc = (unsigned char *)src;

    for(size_t index = 0; index < size; index++) *(cdest + index) = *(csrc + index);
    return dest;
}

C标准不允许对void指针进行任何指针算术运算。 gcc的扩展名将void *视为指向char的指针,允许进行算术运算,但不允许反引用。+

答案 1 :(得分:1)

关于这些警告:

 warning: pointer of type ‘void *’ used in arithmetic [-Wpointer-arit]
  214 |                void *address2 = prev->start + i;
Warning: pointer of type ‘void *’ used in arithmetic [-Wpointer-arit]
  215 |                void *address1 = now->start + i;

在任何现代计算机上,指针的值都是一个内存地址(通常是虚拟内存地址)。将一个指针添加到指针时,它的值(即内存地址)将按所指向类型的大小递增。

示例:

 TYPE* p = SOME_ADDRESS;  // The value of p is now SOME_ADDRESS
 p = p + 1;               // The value of p is now SOME_ADDRESS + sizeof(TYPE);

 p = SOME_ADDRESS;        // The value of p is now SOME_ADDRESS
 p = p + i;               // The value of p is now SOME_ADDRESS + i * sizeof(TYPE);

换句话说:为了向指针添加整数值,我们需要知道指针所指向的元素的大小。

那是你的问题。您有void指针,因此您需要知道“ sizeof void”才能更新指针。但是void的大小可以是任何东西,并且不是标准定义的。显然,您的编译器具有允许sizeof(void)的非标准扩展名。因此,您的编译器只会向您发出警告。

关于此错误:

error: invalid conversion from ‘void*’ to ‘char*’

它来自您未发布的一些代码发布。此外,它表明您使用的是c ++编译器而不是c编译器。

最后:即使指针算术有效,您的代码也无济于事。

    for (int i = now->size - 1; i >= 0; i--)
    {
       void *address2 = prev->start_address + i;
       void *address1 = now->start_adress + i;

       address1 = address2;  // This only change the value of the pointer
                             // It doesn't change the memory that the
                             // pointer points to
       address2 = '\0';
    }

目前尚不清楚您要做什么,但这也许正是您想要的:

    for (int i = now->size - 1; i >= 0; i--)
    {
       char *address2 = (char*)prev->start_address + i;
       char *address1 = (char*)now->start_adress + i;

       *address1 = *address2;
       *address2 = '\0';
    }

答案 2 :(得分:0)

类型void始终是不完整的类型。也就是说,类型void的对象的大小是未知的。因此,尽管某些编译器有自己的语言扩展,允许使用类型为void *的指针算法与使用类型为{的指针的指针算法相同,但您可能不能将指针算法与类型为void *的指针一起使用{1}}。

这些陈述

char *

根据C标准不正确,因为指针void *address2 = prev->start + i; void *address1 = now->start + i; 的类型为start

似乎也有这些陈述

void *

没有做什么事。

对于初学者来说,这句话

address1 = address2;

address2 = '\0';

将一个指针分配给另一个指针,尽管实际上您实际上想将一个指针指向的值分配给另一个指针指向的内存。

此语句等效于

address1 = address2;

那是因为它不会设置带有终止零字符address2 = NULL; 的指针存储器。

如果您所说的这些指针处理一条消息(字符串),那么您需要将指针转换为类型'\0'

关于你的这句话

我调用一个交换功能,以转移内存中的消息:

然后完全不清楚您要使用for循环做什么,因为在任何情况下循环都没有意义。

如果您需要将一个字符数组复制到另一字符数组中,请根据要复制数组的方式和方式使用标准的C函数char *memcpy