2012-01-28 50 views
9

Tôi có hai nghi ngờ về việc sử dụng memmove():Làm thế nào để sử dụng và khi nào là memmove sử dụng tốt trong C?

  • Khi nào sử dụng thích hợp hơn chức năng này thay vì sử dụng chức năng khác (nghĩa là tạo ra chức năng riêng)? Tôi không chắc là tôi đã hiểu đúng.
  • Chữ ký của hàm là void * memmove (void * dest, const void * src, size_t n). Nếu tôi có một mảng đơn giản arr [N], làm thế nào tôi có thể đặt nó vào hàm được gọi? arr [N] hoặc & arr [N]? Sự khác biệt là nếu mảng được khai báo với kích thước ban đầu hoặc giống như một con trỏ? Tôi có nghi ngờ này bởi vì tôi thấy nhiều ví dụ được sử dụng cả hai.

Tôi hy vọng tôi đã giải thích những nghi ngờ của mình theo cách tốt.

chỉnh sửa: Tôi phải xóa phần tử khỏi mảng và sau đó tôi muốn thay đổi các phần tử sau của phần tử đã xóa ở bên trái.

+1

Có liên quan. http://stackoverflow.com/questions/1960991/which-one-to-use-memmove-or-memcpy-when-buffers-dont-overlap –

Trả lời

13
  1. memmove có thể nhanh hơn nhưng có thể sẽ không bao giờ chậm hơn chức năng của bạn để sao chép dữ liệu xung quanh (thường được mã hóa theo cách cẩn thận để di chuyển công cụ theo cách hiệu quả nhất có thể trên kiến ​​trúc hiện tại);
  2. tùy thuộc vào những gì bạn muốn làm với mảng đó ... nếu bạn muốn sao chép nội dung của nó sang mảng khác arr sẽ đủ (và, như tham số chiều dài, bạn nên làm sizeof(*arr)*N trong đó N là số phần tử sao chép).

Nhân tiện, nếu nguồn và đích và bản sao không chồng chéo memcpy có thể nhanh hơn.

Tôi muốn xóa phần tử khỏi mảng và dịch sang trái phần tử của cùng một mảng.

int arr[N]; 
/* ... */ 
/* Let's say you want to remove the element i (error checking on i omitted) */ 
memmove(arr+i, arr+i+1, (N-i-1)*sizeof(*arr)); 
/* or, if you prefer array indexing over pointer arithmetics: */ 
memmove(&arr[i], &arr[i+1], (N-i-1)*sizeof(*arr)); 

(sizeof(*arr) có nghĩa là "có được kích thước của một phần tử của mảng")

+0

Tôi muốn xóa một phần tử khỏi mảng và di chuyển sang trái phần tử của cùng một mảng. – Kyrol

+1

@Kyrol: câu trả lời được cập nhật. –

+2

Lưu ý chỉ có thể 'memcpy' nhanh hơn đối với dữ liệu không trùng lặp; sử dụng 'memcpy' cũng dùng để ghi lại rằng bạn đang sao chép giữa các đối tượng riêng biệt thay vì chuyển các phần tử trong một đối tượng mảng đơn lẻ. –

0

Khi nào sử dụng thích hợp hơn chức năng này thay vì sử dụng chức năng khác (ví dụ: một tạo chức năng riêng)

Nó nhanh hơn "chức năng riêng được tạo".

chữ ký của hàm này là void * memmove (void * dest, const void * src, size_t n). Nếu tôi có một mảng đơn giản arr [N], làm thế nào tôi có thể đặt nó vào hàm được gọi? arr [N] hoặc & arr [N]

Chỉ arr?

+0

Bạn không hiểu gì về câu hỏi thứ hai của mình ?? Tôi cố gắng giải thích cho tôi tốt hơn. Ví dụ: – Kyrol

4

memmove giống như memcpy ngoại trừ mảng đích và nguồn có thể trùng lặp.

Với memcpy bạn hứa rằng các khu vực không chồng chéo cho phép triển khai thực hiện một số tối ưu hóa bổ sung.Vì vậy, memcpy có thể nhanh hơn memmove.

Hàm memmove cần tham số void * đích và đối số nguồn const void *. Nó có nghĩa là bạn có thể gọi hàm với đối số đích và nguồn của kiểu mảng vì chúng sẽ được chuyển đổi thành kiểu con trỏ. Và khi bạn có thể gán bất kỳ loại con trỏ đối tượng không đủ điều kiện nào cho void * hoặc const void *, bạn sẽ không cần bất kỳ phép truyền nào khi gọi hàm.

char src[1024] = {0}; 
char dst[1024]; 

memmove(dst, src, sizeof dst); 
/* src and dst don't overlap you should choose memcpy instead */ 
memcpy(dst, src, sizeof dst); 

Bây giờ thì tốt hơn nên sử dụng memcpy hoặc memmove hơn để mã chức năng của riêng bạn. Trong glibc ví dụ, tùy thuộc vào tập lệnh MCU và kích thước để sao chép, memcpy có thể được thay thế bằng trình biên dịch với một số phiên bản lắp ráp nội tuyến nhanh của memcpy.

+0

+1. cảm ơn. – Kyrol

+0

và nếu src và dst là cùng một mảng ?? bởi vì nghi ngờ là nếu tôi phải xóa một phần tử và dịch chuyển sang trái các phần tử khác sau phần tử đã xóa. – Kyrol

+0

@Kyrol: vẫn còn với 'char src [1024] = {0}' ví dụ. 'memcpy (src, src + 512, 512);' cùng một đối tượng nhưng các vùng không chồng lên nhau: không sao cả. Nhưng 'memcpy (src + 256, src + 512, 512);' các vùng chồng lên nhau, không được, thay vào đó hãy dùng 'memmove'. – ouah

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