根据http://en.cppreference.com/w/cpp/string/byte/memcpy,c ++ memcpy有三个参数:目标,源和大小/字节.它还返回一个指针.为什么会这样?不是足以输入和复制数据的参数.
还是我误解了什么?示例不使用返回值
有没有什么可靠的办法迫使海湾合作委员会(或编译器)中分解出运行时的大小检查memcpy()在循环外(如该尺寸不编译时间常数,但环内常数),专门为各相关尺寸范围内环路而不是反复检查其中的大小?
这是一个测试案例,从这里报告的性能回归中减少了一个开源库,该库设计用于大数据集的高效内存中分析.(回归恰好是因为我的一个提交...)
原始代码在Cython中,但我已将其简化为纯C代理,如下所示:
void take(double * out, double * in,
int stride_out_0, int stride_out_1,
int stride_in_0, int stride_in_1,
int * indexer, int n, int k)
{
int i, idx, j, k_local;
k_local = k; /* prevent aliasing */
for(i = 0; i < n; ++i) {
idx = indexer[i];
for(j = 0; j < k_local; ++j)
out[i * stride_out_0 + j * stride_out_1] =
in[idx * stride_in_0 + j * stride_in_1];
}
}
Run Code Online (Sandbox Code Playgroud)
步伐是可变的; 一般来说,数组甚至不能保证是连续的(因为它们可能是较大数组的非连续切片.)但是,对于c连续数组的特殊情况,我已将上述内容优化为以下内容: …
假设您有一个类型对象T和一个适当对齐的内存缓冲区alignas(T) unsigned char[sizeof(T)].如果您使用std::memcpy从类型对象复制T到unsigned char数组,是否考虑复制构造或复制分配?
如果一个类型可以轻易复制而不是标准布局,那么可以想象一个类如下:
struct Meow
{
int x;
protected: // different access-specifier means not standard-layout
int y;
};
Run Code Online (Sandbox Code Playgroud)
可以像这样实现,因为编译器不会被强制使用标准布局:
struct Meow_internal
{
private:
ptrdiff_t x_offset;
ptrdiff_t y_offset;
unsigned char buffer[sizeof(int) * 2 + ANY_CONSTANT];
};
Run Code Online (Sandbox Code Playgroud)
编译器可以存储x和y喵的缓冲器内的任何部分buffer,甚至可能在随机内的偏移buffer,只要它们被适当地对准和不重叠.的偏移x和y可即使编译愿与各施工随机变化.(如果编译器希望,x可以继续y使用,因为标准只要求相同访问说明符的成员按顺序排列,x并且y具有不同的访问说明符.)
这将符合可轻易复制的要求; a memcpy将复制隐藏的偏移字段,因此新副本将起作用.但有些事情是行不通的.例如,持有指向x跨越a 的指针memcpy会破坏:
Meow a;
a.x …Run Code Online (Sandbox Code Playgroud) 我有一个std::vector<std::uint8_t>,需要重复.只需调用复制构造函数即可完成此操作.
我的分析结果显示,Microsoft Visual C++(msvc100)实现在std::uninitialized_copy内部使用.这将逐个复制每个元素.在这种情况下,可以通过一次复制整个存储块来完成更优化的复制(就像memcpy可能一样).
换句话说,这可能是一个重要的优化.有没有办法强制矢量使用这种优化方法?
注意:我尝试过使用std::basic_string<std::uint8_t>它确实表现更好,但它有其他问题.
在什么情况下我应该期望memcpys在现代INTEL/AMD硬件上的性能优于其他?我在32位Intel平台上使用GCC 4.2.x(但我对64位感兴趣).
有些人似乎认为C的strcpy()功能是坏的还是邪恶的.虽然我承认通常最好使用strncpy()以避免缓冲区溢出,但以下(strdup()对于那些不够幸运的人来说,这个函数的实现)安全地使用strcpy()并且永远不会溢出:
char *strdup(const char *s1)
{
char *s2 = malloc(strlen(s1)+1);
if(s2 == NULL)
{
return NULL;
}
strcpy(s2, s1);
return s2;
}
Run Code Online (Sandbox Code Playgroud)
*s2保证有足够的空间来存储*s1,并且使用使得strcpy()我们不必将strlen()结果存储在另一个函数中以便稍后用作不必要的(在这种情况下)长度参数strncpy().然而,有些人用strncpy()或甚至memcpy()都需要长度参数来编写这个函数.我想知道人们对此的看法.如果您认为strcpy()在某些情况下是安全的,请说明.如果你有充分的理由不在strcpy()这种情况下使用,请给它 - 我想知道为什么使用strncpy()或memcpy()在这种情况下可能更好.如果你认为strcpy()没问题,但不在这里,请解释.
基本上,我只是想知道为什么有些人memcpy()在别人使用时使用,strcpy()而其他人则使用普通用户strncpy().是否有任何逻辑可以优先选择三个(忽略前两个的缓冲区检查)?
直到最近,我才看到复制完成的结构字段memcpy().在类和在线指令中,将一个结构的内容复制到另一个结构中通常看起来像
struct block *b0 = malloc(sizeof(struct block));
struct block *b1 = malloc(sizeof(struct block));
/* populate fields in *b0 */
memcpy(b1, b0, sizeof *b1); /* copy contents of b0 into b1 */
/* free b0, b1 */
Run Code Online (Sandbox Code Playgroud)
但是,这个任务也可以通过简单的分配来替换memcpy().
*b1 = *b0; /* dereferenced struct assignment */
Run Code Online (Sandbox Code Playgroud)
有没有充分的理由说明为什么它没有被广泛使用(至少在我有限的经验中)?这两种方法是分配和memcpy()等价的,还是有一些令人信服的理由memcpy()一般使用?
是使用未初始化的变量作为src对memcpy用C未定义行为?
void foo(int *to)
{
int from;
memcpy(to, &from, sizeof(from));
}
Run Code Online (Sandbox Code Playgroud) 标准C函数'memcpy'如何工作?它必须将(大)RAM块复制到RAM中的另一个区域.因为我知道你不能在汇编中直接从RAM移动到RAM(使用mov指令)所以我猜它在复制时使用CPU寄存器作为中间存储器?
但它是如何复制的?通过块(如何通过块复制?),按单个字节(char)或它们具有的最大数据类型(复制在long long double中 - 在我的系统上为12个字节).
编辑:好的,显然你可以直接将数据从RAM移动到RAM,我不是装配专家,所有我学习的装配都来自这个文件(X86装配指南),在关于不能从中移动的mov指令的部分中提及RAM到RAM.显然这不是真的.
我想将一个int数组复制到另一个int数组.它们使用相同的长度定义,因此它们总是具有相同的长度.
memcpy()的size参数的以下两个替代方法的优缺点是什么?
memcpy(dst, src, ARRAY_LENGTH*sizeof(int));
Run Code Online (Sandbox Code Playgroud)
要么
memcpy(dst, src, sizeof(dst));
Run Code Online (Sandbox Code Playgroud)
第二种选择总能奏效吗?无论内容如何?
有利于最后一件事的一件事是,如果阵列要改变,那么更新memcpy()将是一些内容管理.
谢谢