7 Ağustos 2020 Cuma

std::memcpy metodu

Giriş
source ve destination alanları çakışamaz. Açıklaması şöyle. Bu tür problemlerle uğraşmamak için belki en iyisi her zaman memmove() metodunu kullanmak.
The memcpy() function copies n bytes from memory area src to memory area dest. The memory areas must not overlap. Use memmove(3) if the memory areas do overlap.
İmzası şöyle.
void *memcpy (void *restrict dest, const void restrict *src, size_t n);
Açıklaması şöyle.
The memcpy function returns the value of dest
ISO 1990 standardındaki açıklama şöyleydi. Yani destination parametresini dönüyordu
Returns

The memcpy function returns the value of s1
Açıklaması şöyle. Aynı çok eskiden her metod bir sonuç döndüğü için böyle yazmışlar
In early versions of the C language, every function would return something, whether or not the caller would make use of the returned value. Generally, the return value of a function would be whatever happened to be in some particular register of the appropriate type. If code exited a function without making any effort to set the register to something meaningful, and calling code ignored the contents of the register in question, having the function nominally return a meaningless value was simpler and easier than providing a means of having functions not return a value.

I don't think any particular thought was put into the question of what functions like memcpy, strcpy, or strcat should return, but the authors of the Standard didn't want to simply leave the return value unspecified. Since there may have been platforms where functions that don't return a value would be processed differently from those that do, giving such functions a void return type could have broken code that calls the functions without including the appropriate standard header.

Overlap Meselesi
Örnek - overlap
Şöyle yaparsak yanlış olur. Çünkü okuma yaptığımız alan ile yazma yaptığımız alan arr[2] bölgesinde çakışıyor.
char arr[10];
// Code that does something
memcpy(&arr[0], &arr[3], 5);
Ama bu kod yanlış değildir.
memcpy(&arr[0], &arr[3], 2);
Örnek
Doğru ve yanlış memcpy kullanımı. Şöyle yaparız.
char a[16];
char b[16];

memcpy(a,b,16);           // valid
memmove(a,b,16);          // Also valid, but slower than memcpy.
memcpy(&a[0], &a[1],10);  // Not valid since it overlaps.
memmove(&a[0], &a[1],10); // valid. 
Kullanım
Örnek
Aynı tipten iki nesne birbirine kopyalanabilir. Şöyle yaparız.
T* t1p;
T* t2p;
// provided that t2p points to an initialized object ...
std::memcpy(t1p, t2p, sizeof(T));
// at this point, every subobject of trivially copyable type in *t1p contains
// the same value as the corresponding subobject in *t2p
Örnek
Nesne char buffer'a kopylanabilir. Şöyle yaparız.
#define N sizeof(T)
char buf[N];
T obj;                    // obj initialized to its original value
std::memcpy(buf, &obj, N);// between these two calls to std​::​memcpy, obj might be modified
std::memcpy(&obj, buf, N);// at this point, each subobject of obj of scalar type holds
                          //its original value
Örnek
Açıklaması şöyle.
Copies count bytes from the object pointed to by src to the object pointed to by dest. Both objects are reinterpreted as arrays of unsigned char.
Nesne aynı veya daha büyük bir alana kopyalanabilir. Şöyle yaparız.
float f = ...;
uint32_t i;
static_assert(sizeof(f)==sizeof(i));
std::memcpy(&i, &f, sizeof(i));
// use i to extract f's sign, exponent & significand
Örnek
float* buffer'a double yazmak için şöyle yaparız.
void set(float *buffer, size_t index, double value) {
  memcpy(reinterpret_cast<char*>(buffer)+sizeof(double)*index, &value, sizeof(double));
}
double get(const float *buffer, size_t index) {
  double v;
  memcpy(&v, reinterpret_cast<const char*>(buffer)+sizeof(double)*index, sizeof(double));
  return v;
}
void f(float *buffer) {
  // here, use set and get functions
}
Copy Constructor Olarak memcpy 
Şu kod yanlıştır.
class A{
  public:
    int ID;
    virtual A* copy(){
      return new A();
    }
}

class B : public A{
  public:
    int subID;
    virtual A* copy(){
      B* b = new B();
      memcpy (b,this,sizeof(B));
      return b;
    }
};
Şöyle bir hata alırız.
destination for this 'memcpy' call is a pointer to dynamic class 'B' ;
 vtable pointer will be overwritten
explicitly cast the pointer to silence this warning
Açıklaması şöyle
C++ objects should not be copied with the C library's memcpy() function (except in certain limited situations), which knows nothing about C++ classes, their constructors, destructors, virtual methods, and everything else that's in C++ that's not in C.

Hiç yorum yok:

Yorum Gönder