int a = 10;
int* pA = &a;
long long b = 200;
long long* pB = &b;
memcpy (pB,pA,4);
memcpy (pB+1,pA,4);
cout<<"I'm a memcpy!: "<<*(pB)<<endl;
我正在用memcpy做一些测试来教自己记忆是如何工作的。我想要做的是使b =到“1010”。我可以将值从a复制到b,但是然后我尝试将内存偏移1个字节并写入另外10个但是它不起作用它只输出“10”。
我需要做些什么来获得值1010?
答案 0 :(得分:9)
您的代码存在一些问题:
int
类型。由于int
不保证是任何特定大小,因此在执行此类memcpy
之前,您需要确保它至少有4个字节。memcpy
适用于字节级别,但整数是一系列字节。根据您的目标体系结构,整数内的字节可能会以不同的方式排列(big-endian,little-endian等)。在整数上使用memcpy
可能会也可能不会达到预期效果。在学习memcpy
和朋友的工作方式时,最好使用字节数组。memcpy
使用pB+1
作为目标。这不会使指针前进一个字节,而是将其提前sizeof(*pB)
个字节。在这种情况下,它使它指向一个无效的地址(超过变量的末尾)。对memcpy
的此调用将破坏随机内存,这可能会导致程序崩溃或导致不可预测的结果。答案 1 :(得分:2)
我认为memcpy()
不是为你想要的而设计的。通常,您可以使用memcpy()
复制一个或多个整个对象(对象可能是int,char,long long等)。
int a[4] = { 1, 2, 3, 4 };
int b[3];
int c[5] = { 0 };
::memcpy(b, a, 3 * sizeof(int)); // b is { 1, 2, 3 }
::memcpy(c+2, b, 3 * sizeof(int)); // c is { 0, 0, 1, 2, 3 }
c + 2不是“c + 2字节”。它是“c + 2 ints”(Win32 / x86系统上的8个字节)。
你可以通过强制转换为char或unsigned char指针来访问各个字节,但除非你真正理解你正在做什么,否则我不建议这样做,因为存在许多陷阱。
unsigned x = 0;
unsigned char *px = reinterpret_cast<unsigned char *>(&x);
px[0] = 0xFF;
px[2] = 0xAA;
这里的一个危险是您正在假设计算机如何存储整数。在x86系统上,x将为0x00AA00FF,但在Sun Sparc系统上,它将为0xFF00AA00。
如果您需要设置整数的部分,通常最好使用“或”和“shift”。
x = (0xFF<<24) | (0xAA<<8);
将在任何架构上为您提供0xFF00AA00。 0xFF&lt;&lt; 24将值0xFF向左移24位,产生0xFF000000。 0xAA&lt;&lt; 8将值0xAA向左移8位,产生0x0000AA00。
我们“或”他们在一起,给出0xFF00AA00。
答案 2 :(得分:1)
查看指针算术:http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/BitOp/pointer.html。向指针添加值实际上会增加您正在处理的任何大小的单位。
答案 3 :(得分:0)
pB的类型为long long *,因此向它添加1将为变量b后面的下一组8个字节提供地址。你有pB [0]是变量b,但是pB [1](相当于pB + 1)指向未定义的内存。写入它可能会导致崩溃。
替换
long long b;
与
long long b[2];
(使用您喜欢的任何初始值)
你的cout需要同时喂b [0]和b [1]。
答案 4 :(得分:0)
如果你想复制&#34; 10&#34;以后到字节并得到&#34; 1010&#34;,你想要复制字符串。这实际上是strcat()
而非memcpy()
的工作,但是您可以通过memcpy()
来实现这一目标:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
constexpr char src[] = "10";
constexpr size_t n = sizeof(src) - 1; // Don’t count the terminator.
char dest[2*n+1] = {'\0'}; // Will hold: {'1','0','1','0','\0'}
static_assert( sizeof(dest) > 2*n, "" ); // Always check array bounds in C++!
memcpy( dest, src, n );
memcpy( dest + n, src, n );
puts(dest);
return EXIT_SUCCESS;
}
特别是,请注意目标是一个足以容纳两个副本的字节数组。
答案 5 :(得分:0)
我的信誉评分> = 50,所以我也无法发表评论,即使是被评论的帖子的原始作者->从我的角度来看这也是愚蠢的...
因此,这是我对user207421发表的评论的回答:
SIMD指令至少在最近20年中已在PC上使用的每个CPU中实现,因此,除非您使用的是非常个旧CPU,否则您对“ “ CPU基本上是无效的。
请参阅我上面的帖子中的第2点:“最快的依赖于体系结构的方法”意味着在8位AVR上,“ movw”指令可以(且用于)实现类似memcpy的快速功能,因为它的工作方式类似于x86上的SIMD:它可以在一个周期内复制2个8位CPU字
致谢。
答案 6 :(得分:-1)
memcpy在字节级别上工作,但整数是一系列字节。
错误的解释。
对于strcpy()
,上述答案或多或少都是正确的,但在memcpy()
的情况下完全错误,因为所有mem_xxx()
函数都使用SIMD指令来加速操作。
如果memcpy()
函数基于逐字节复制,那将会非常慢......
基本上,所有mem_xxx
函数都是这样实现的:
我建议在发布错误答案之前实际读取代码。