将数据从一个范围复制到另一个范围时,如果源范围和目标范围之间存在部分重叠,则必须小心.如果目标范围的开头与源范围的尾部重叠,则普通顺序副本将使数据混乱.C运行时库具有memmove除memcpy处理这种重叠的问题.
我假设这样的std::copy工作memcpy,因为它不考虑源和目标区域之间的重叠.如果您尝试在std::vectorwith中"向下"移动对象std::copy,则会破坏数据.是否有STL算法类似于memmove处理这样的情况?或者我应该使用反向迭代器自己滚动?
我最近发现需要std::string用自己的子串替换内容.在这里调用最合乎逻辑的函数我认为如下,来自http://www.cplusplus.com/reference/string/string/assign/:
substring(2) string&assign(const string&str,size_t subpos,size_t sublen);
复制从字符位置subpos开始的str部分并跨越sublen字符(或者直到str的结尾,如果str太短或者如果sublen是string :: npos).str
另一个字符串对象,其值可以复制或移动.subpos
作为子字符串复制到对象的str中第一个字符的位置.如果这大于str的长度,则抛出out_of_range.注意:str中的第一个字符用值0表示(不是1).sublen
要复制的子字符串的长度(如果字符串较短,则复制尽可能多的字符).string :: npos的值表示直到str结尾的所有字符.
但是,我不确定这是否允许,或者它是否可以破坏字符串数据.我知道memcpy(),例如,不允许(或至少不能保证的情况下,非腐败)覆盖的内存区域用(的一部分)本身(见的memcpy()VS的memmove() ).但我不知道上述方法是否有相同的限制.
更一般地说,如果我能够自己找出这个问题的答案,请你评论一下吗?我没有什么链接到该文件中清楚地给我这个问题的答案是什么,除了可能的限定词"另一个"在的描述str参数(" 另一个字符串对象"),这似乎意味着它不能在此对象,虽然我不觉得这是毫不含糊的.这是文档中的弱点吗?
这是C11标准的引用:
6.5表达式
......6 访问其存储值的对象的有效类型是对象的声明类型(如果有).如果通过具有非字符类型的左值的值将值存储到没有声明类型的对象中,则左值的类型将成为该访问的对象的有效类型以及不修改该值的后续访问的有效类型储值.如果使用
memcpy或将值复制到没有声明类型的对象中memmove,或者将其复制为字符类型数组,则该访问的修改对象的有效类型以及不修改该值的后续访问的有效类型是有效类型复制值的对象,如果有的话.对于没有声明类型的对象的所有其他访问,对象的有效类型只是用于访问的左值的类型.7对象的存储值只能由具有以下类型之一的左值表达式访问:
- 与对象的有效类型兼容的类型,
- 与对象的有效类型兼容的类型的限定版本,- 与对象
的有效类型对应的有符号或无符号类型的类型,
- 类型这是对象的有效类型的限定版本对应的有符号或无符号类型,
- 聚合或联合类型,包括其成员中的上述类型之一(包括递归地,子聚合或包含联合的成员) ,或
- 字符类型.
这是否意味着memcpy不能以这种方式用于打字:
double d = 1234.5678;
uint64_t bits;
memcpy(&bits, &d, sizeof bits);
printf("the representation of %g is %08"PRIX64"\n", d, bits);
Run Code Online (Sandbox Code Playgroud)
为什么它不会给出相同的输出:
union { double d; uint64_t i; } u;
u.d = 1234.5678;
printf("the representation of %g is %08"PRIX64"\n", d, u.i);
Run Code Online (Sandbox Code Playgroud)
如果我使用我的memcpy使用字符类型的版本怎么办:
void *my_memcpy(void *dst, const void *src, size_t n) {
unsigned char …Run Code Online (Sandbox Code Playgroud) 使用Aztec线性系统求解器库时,我遇到了奇怪的行为.使用valgrind,我发现这个库memcpy在重叠缓冲区上执行.规范说明memcpy没有定义重叠缓冲区的行为.
事实证明,memcpy在许多机器上具有与使用for循环一样的行为,因此您可以安全地从较高的源复制到较低的目标:
for(int i = 0; i < len; i ++)
dest[i] = source[i];
Run Code Online (Sandbox Code Playgroud)
但是在我们的大型集群上,memcpy重叠缓冲区具有不同的行为,这会导致问题.
现在我想知道memcpy库中的重叠是正常的还是仅仅是由我的代码中的另一个错误引起的.由于库被广泛使用,我认为memcpy应该早先发现该问题.另一方面,绝大多数memcpy实现仍然可能像for循环一样,因此没有人遇到过这个问题.
memcpy在各种机器上重叠的经历?memcpy?我想指出的问题是关于各种实现的实际经验,而不是规范所说的内容.
我正在浏览memmove()与memcpy()Stack Overflow 相关的各种问题.
这篇文章暗示如果源地址(要复制的数据)大于目标地址(要复制的数据),它将执行正向复制,否则将执行向后复制.
为什么会那样?我尝试了两种情况下的复制,并且完美无缺,没有任何错误.
你能详细说明吗?我没理由.
编辑:这就是我的意思:
#include <memory.h>
#include <string.h>
#include <stdio.h>
void *memmoveCustom(void *dest, const void *src, size_t n)
{
unsigned char *pd = (unsigned char *)dest;
const unsigned char *ps = (unsigned char *)src;
if ( ps < pd )
for (pd += n, ps += n; n--;)
*--pd = *--ps;
else
while(n--)
*pd++ = *ps++;
return dest;
}
int main( void )
{
printf( "The string: %s\n", str1 );
memmoveCustom( str1 + …Run Code Online (Sandbox Code Playgroud) 可能的重复:
memcpy 与 memmove
memmove实际上“移动”了一块内存吗?如果是这样,内存中是否会留下零?或者,它就像memcpy一样吗?我正在查看手册页,我不相信我的假设是正确的。如果我想使用 memmove 移动一块内存,我是否必须手动将移动的内存块清零?
我正在使用clangDebian 8系统.我有标准的C++标头.然而,没有标题定义strcpy_s.为什么是这样?
# grep -iRHI 'strcpy_s' /usr 2>/dev/null
/usr/include/x86_64-linux-gnu/bits/string2.h: ? __strcpy_small (dest, __strcpy_args (src), \
/usr/include/x86_64-linux-gnu/bits/string2.h:__STRING_INLINE char *__strcpy_small (char *, __uint16_t, __uint16_t,
/usr/include/x86_64-linux-gnu/bits/string2.h:__strcpy_small (char *__dest,
/usr/include/x86_64-linux-gnu/bits/string2.h:__STRING_INLINE char *__strcpy_small (char *, __STRING2_COPY_ARR2,
/usr/include/x86_64-linux-gnu/bits/string2.h:__strcpy_small (char *__dest,
/usr/src/broadcom-sta-6.30.223.248/src/include/bcmutils.h:#define bcm_strcpy_s(dst, noOfElements, src) strcpy((dst), (src))
Run Code Online (Sandbox Code Playgroud) 据我所知,memmove在C(cstring库)中处理很好地" 以较慢的运行时为代价 "(参见这篇文章).我想知道为什么这个额外的运行时成本?在我看来,任何重叠问题都可以通过向后复制而不是向前复制来解决,我错了吗?
作为一个玩具示例,这里有两个版本的"右移"函数,它将数组的内容移动右侧的一个元素:
// Using memmove
template <typename T>
void shift_right( T *data, unsigned n )
{
if (n)
{
data[n-1].~T();
memmove( data+1, data, (n-1)*sizeof(T) );
new (data) T();
}
}
// Using copy_backward
template <typename Iterator>
void shift_right( Iterator first, Iterator last )
{
Iterator it = last;
std::copy_backward( first, --it, last );
}
Run Code Online (Sandbox Code Playgroud)
它们是等价的吗?性能方面,哪一个最好用?
注意:根据@DieterLücking的评论判断,尽管采取了预防措施,上述版本的使用memmove在这种情况下是不安全的.
7.24.2.2“ memmove功能”:
该
memmove函数将n字符从指向的对象复制到指向s2的对象s1。复制发生就好像n从对象人物指向s2首先拷贝到一个临时数组n字符不重叠的对象指向s1和s2,然后n从临时数组字符复制到对象指向s1
因此,如果我选择使用(file_size = 32K)移动大小为32K的缓冲区
memmove(io_Buffer, io_Buffer+17, file_size);
Run Code Online (Sandbox Code Playgroud)
临时缓冲区的大小不是32K吗?
题
程序可以自行分配动态内存吗?它会在那一行中分配和释放内存吗?
我正在使用一个位置向右memmove移动std::string元素.目的地的第一个地方是唯一被弄乱并充满垃圾的地方.我正在使用memmove而不是strcpy因为我在需要模板的类中使用它.当我有一系列的int时,它工作正常.有关如何修复字符串的任何想法?
/**
* @brief Shifts elements in the array to the right
* @param newItem The insert position.
*/
template<class T>
void DynamicArray<T>::shiftElementsRight(uint newItem) {
uint diff = _size - newItem;
memmove(&(_array[newItem + 1]),
&(_array[newItem]), sizeof(_array[0]) * diff);
}
Run Code Online (Sandbox Code Playgroud)
我的主要
int main() {
DynamicArray<string> array(1);
string val1 = "val1";
array.add(val1);
string val2 = "val2";
array.add(val2);
// ... more additions ...
Run Code Online (Sandbox Code Playgroud)
最后一个输出:
Sizeof: 8
Value is: val1
Value is: val11val3, val21
????[val1, val2A????[val1, …Run Code Online (Sandbox Code Playgroud)