是否可以使用memcpy()复制包含指针的结构?

RLe*_*vre 3 c++ struct memcpy

前几天我正在考虑这个问题,如果这是一个坏主意我很好奇...让我们说有一个结构包含一个指向字符串数组的指针.memcpy()会复制下面示例中的'name'数组指针吗?编辑:此示例中无法访问std.

struct charMap
{ 
  unsigned char * name;   
  unsigned char id;       
};
typedef struct charMap CharMapT;

class ABC
{
  public:
  ABC(){}
  void Function();
  CharMapT* structList;
}

void ABC::Function ()
{
  CharMapT list[] = 
  {
    {"NAME1", 1},
    {"NAME2", 2}, 
    {"NAME3", 3}
  };

  structList = new CharMapT[sizeof(list)];
  memcpy(structList, &list, sizeof(list));
}
Run Code Online (Sandbox Code Playgroud)

Who*_*aig 6

在我们将要讨论的代码中有几个错误,我将首先讨论这个错误,然后是指针与数组的指针.

struct charMap
{ 
  unsigned int * name;   
  unsigned int id;       
};
typedef struct charMap CharMapT;
Run Code Online (Sandbox Code Playgroud)

这声明了一种结构类型,其中包含指向unsigned int的指针作为第一个成员(name),int作为第二个成员(id).在具有默认字节打包的32位系统上,这将是8字节宽(32位指针= 4字节,32位符号int = 4字节).如果这是一个64位机器,指针将是8字节宽,int仍然可能是32位宽,使结构大小为12字节.

可疑代码

void ABC::Function ()
{
  CharMapT list[] = 
  {
    {"NAME1", 1},
    {"NAME2", 2}, 
    {"NAME3", 3}
  };

  structList = new CharMapT[sizeof(list)];
  memcpy(structList, &list, sizeof(list));
}
Run Code Online (Sandbox Code Playgroud)

这将分配CharMapT结构的动态数组.多少?比你想象的更多.在sizeof(list)将返回的字节数list[]阵列.由于CharMapT结构宽度为8个字节(见上文),因此这将是3*8或24个CharMapT项目(如果使用64位指针则为36项).

然后,我们memcpy()24 个字节从(或36个字节)list(在&&list是不必要的)到新分配的内存.这将复制3个CharMapT结构,留下我们分配的其他21个(超出其初始默认构造).

注意:你正在初始化一个const char *声明为的字段unsigned int *,所以如果这甚至编译了基本数据类型会有所不同.假设您修改了结构并将指针类型更改为const char *,则const数据段中某处的静态字符串常量地址("NAME"常量的地址)将分配给structList [0]中元素的指针变量.name,structList [2] .name和structList [3] .name分别.

这将不复制数据指出.它只会复制指针.如果你想要数据的副本,那么你必须对它们进行原始分配(malloc,new,等等).

更妙的是,使用std::vector<CharMapT>,使用std::stringCharMapT::name,并使用std::copy()复制源(甚至直接分配).

我希望能解释你在寻找什么.


Pointer与Array Diatribe

切勿将指针与数组混淆.指针是一个可变的是保持一个地址.就像int变量保存整数值或char变量保存字符类型一样,指针中保存的值是地址

数组是不同的.它也是一个变量(显然),但它不能是l值,几乎每个地方通常都会使用转换.从概念上讲,转换会产生一个指向数组数据类型的临时指针,并保存第一个元素的地址.有些时候,这种概念并没有发生(如应用地址运算符).

void foo(const char * p)
{
}

char ar[] = "Hello, World!";
foo(ar); // passes 'ar', converted to `char*`, into foo. 
         // the parameter p in foo will *hold* this address
Run Code Online (Sandbox Code Playgroud)

或这个:

char ar[] = "Goodbye, World!";
const char *p = ar;  // ok. p now holds the address of first element in ar
++p;                 // ok. address in `p` changed to address (ar+1)
Run Code Online (Sandbox Code Playgroud)

但不是这个:

char ar[] = "Goodbye, World!";
++ar; //  error. nothing to increment.
Run Code Online (Sandbox Code Playgroud)