2012-11-12 33 views
10

Từ manpage Linux cho memmove(3)Tại sao Linux memmove() thực hiện theo cách của nó?

Các memmove() bản sao chức năng n byte từ vùng nhớ src đến khu vực bộ nhớ dest. Khu vực bộ nhớ có thể trùng lặp: sao chép diễn ra như thể các byte trong src là được sao chép lần đầu vào một mảng tạm thời không trùng lặp src hoặc dest và sau đó được sao chép từ mảng tạm thời đến đích.

Thay vì phân bổ một mảng tạm thời và sao chép các giá trị gấp đôi chúng ta chỉ có thể làm như sau:

void *my_memmove(void *dest, const void *src, size_t n) { 
    signed char operation; 
    size_t end; 
    size_t current; 

    if(dest != src) { 
    if(dest < src) { 
     operation = 1; 
     current = 0; 
     end = n; 
    } else { 
     operation = -1; 
     current = n - 1; 
     end = -1; 
    } 

    for(; current != end; current += operation) { 
     *(((unsigned char*)dest) + current) = *(((unsigned char*)src) + current); 
    } 
    } 
    return dest; 
} 

Thực hiện điều này, chúng tôi chỉ đơn giản là chăm sóc các vị trí mà chúng ta bắt đầu sao chép.

Có hạn chế trong việc triển khai của tôi không?

Lưu ý: Tôi sẽ không thực sự sử dụng triển khai của mình. Tôi chỉ tò mò thôi.

+4

'dest

+12

Tôi nghĩ bạn đã bỏ lỡ "như thể" trong manpage. Nó không thực sự hoạt động theo cách đó. – dbrank0

+0

Bạn có thể so sánh việc triển khai của mình với [bcopy' của FreeBSD] (http://fxr.watson.org/fxr/source/string/bcopy.c?v=FREEBSD-LIBC), mã cơ bản cho memmove() của chúng. Nó cũng hỗ trợ sao chép ngược, không có bộ đệm tạm thời. – ShiDoiSi

Trả lời

22

Bạn có thể xem xét một số mã nguồn cho memmove here, here, here, và here.

Điều bạn sẽ nhận thấy là chúng không thực sự tạo một mảng tạm thời. Các trang của người đàn ông được viết để giúp bạn hiểu những gì nó đang làm một cách hợp lý, không phải thực sự là. Do đó, họ nói "như thể".

Những gì memmove() thực sự làm là sao chép các byte từ src đến dest và bản sao chuyển tiếp nếu dest < src (về cơ bản giống như memcpy) và ngược lại.

Sự khác biệt giữa memcpymemmovememcpy các bản sao bị mù về phía trước - đó là lý do tại sao destsrc không được chồng lên nhau. Nhưng memmove có biện pháp phòng ngừa đảm bảo chồng chéo sẽ không làm hỏng kết quả cuối cùng.

+2

Điểm tuyệt vời. Ghi nhớ nguồn C cho Linux là [ở đây] (http://sourceware.org/git/?p=glibc.git;a=blob;f=string/memmove.c;h=bf7dcc162770503ed62a262f627bfa526fc5a0d7;hb=HEAD), nhưng nó phần lớn không liên quan vì thực tế 'memmove' được thực hiện [trong assembly được tối ưu hóa bằng tay] (http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/x86_64/memcpy.S; h = 9e693f2a9806fa8f6ce7e26f37b1808e952396d3; hb = HEAD), mà chắc chắn không sao chép vào một mảng temp. Như một sự tò mò, nó được định nghĩa chính xác giống như 'memcpy', bởi vì trên kiến ​​trúc đích của nó không có hình phạt nào khi làm theo cách đó. – user4815162342

Các vấn đề liên quan