strcpy so với memcpy


81

Sự khác biệt giữa memcpy()và là strcpy()gì? Tôi đã cố gắng tìm nó với sự trợ giúp của một chương trình nhưng cả hai đều cho cùng một đầu ra.

int main()
{
    char s[5]={'s','a','\0','c','h'};
    char p[5];
    char t[5];
    strcpy(p,s);
    memcpy(t,s,5);
    printf("sachin p is [%s], t is [%s]",p,t);
    return 0;
}

Đầu ra

sachin p is [sa], t is [sa]

Câu trả lời:


127

có thể làm gì để thấy hiệu ứng này

Biên dịch và chạy mã này:

void dump5(char *str);

int main()
{
    char s[5]={'s','a','\0','c','h'};

    char membuff[5]; 
    char strbuff[5];
    memset(membuff, 0, 5); // init both buffers to nulls
    memset(strbuff, 0, 5);

    strcpy(strbuff,s);
    memcpy(membuff,s,5);

    dump5(membuff); // show what happened
    dump5(strbuff);

    return 0;
}

void dump5(char *str)
{
    char *p = str;
    for (int n = 0; n < 5; ++n)
    {
        printf("%2.2x ", *p);
        ++p;
    }

    printf("\t");

    p = str;
    for (int n = 0; n < 5; ++n)
    {
        printf("%c", *p ? *p : ' ');
        ++p;
    }

    printf("\n", str);
}

Nó sẽ tạo ra đầu ra này:

73 61 00 63 68  sa ch
73 61 00 00 00  sa

Bạn có thể thấy rằng "ch" đã được sao chép bởi memcpy(), nhưng không phải strcpy().


1
Xin chào, tôi biết bài đăng đó đã cũ, nhưng tôi có hai câu hỏi liên quan đến nó. Đầu tiên - printf("%2.2x ", *p);- tại sao Bạn lại giới hạn printf thành 2.2? Ngoài ra tôi có thể thấy KHÔNG có chấm nào cả ... Thứ hai - printf("%c", *p ? *p : ' ');- bài kiểm tra này thực sự kiểm tra điều gì? Nếu *p? Chân thành cám ơn vì câu trả lời của bạn!
Peter Cerba

14
Trong câu lệnh printf, "x" có nghĩa là "cơ số 16". "2.2" có nghĩa là: hai và chỉ hai chữ số. Bài *pkiểm tra có nghĩa là: "nếu bạn nhấn một giá trị rỗng, hãy in ra một khoảng trắng."
egrunin,

85

strcpydừng lại khi nó gặp ký tự NUL ( '\0'), memcpythì không. Bạn không thấy hiệu ứng ở đây, vì %strong printf cũng dừng ở NUL.


2
@Sachin: Khởi tạo ptđến một cái gì đó (ví dụ: tất cả các khoảng trống), sau đó sau khi sao chép, hãy so sánh p[3]với t[3]. Các strcpykhông đi xa hơn p[2], nơi mà nó tìm thấy các ký tự null, nhưng memcpytheo chỉ dẫn sao chép năm nhân vật.
Cascabel

9
Nhặt nit nhỏ: strcpy dừng khi nó gặp ký tự NUL (một "L"). NULL (hai "L") là hằng số thời gian biên dịch cho một con trỏ được đảm bảo không trỏ đến bất kỳ đối tượng hợp lệ nào.
Daniel Stutzbach

Cảm ơn, tôi đã có câu trả lời
Sachin Chourasiya

nếu đích và src trùng nhau, strcpy sẽ tạo ra một lỗi seg?
Alcott

12

strcpychấm dứt khi tìm thấy dấu chấm hết rỗng của chuỗi nguồn. memcpyyêu cầu một tham số kích thước được truyền. Trong trường hợp bạn đã trình bày, printfcâu lệnh đang tạm dừng sau khi tìm thấy dấu chấm dứt rỗng cho cả hai mảng ký tự, tuy nhiên bạn cũng sẽ tìm thấy t[3]t[4]đã sao chép dữ liệu trong chúng.


9

strcpy sao chép từng ký tự từ nguồn đến đích cho đến khi tìm thấy ký tự NULL hoặc '\ 0' trong nguồn.

while((*dst++) = (*src++));

trong khi memcpy sao chép dữ liệu (không phải ký tự) từ nguồn đến đích có kích thước n cho trước, bất kể dữ liệu trong nguồn.

memcpynên được sử dụng nếu bạn biết rõ rằng nguồn chứa ngoài ký tự. đối với dữ liệu được mã hóa hoặc dữ liệu nhị phân, memcpy là cách lý tưởng để sử dụng.

strcpykhông được dùng nữa, vì vậy hãy sử dụng strncpy.


3

Do ký tự null trong schuỗi của bạn , chuỗi printfsẽ không hiển thị bất cứ điều gì ngoài đó. Sự khác biệt giữa ptsẽ ở ký tự 4 và 5. psẽ không có bất kỳ ký tự nào (chúng sẽ là rác) và tsẽ có 'c''h'.


2
  • Sự khác biệt về hành vi: strcpydừng lại khi nó gặp phảiNULL hoặc'\0'
  • Hiệu suất khác biệt: memcpythường hiệu quả hơn strcpy, luôn luôn quét dữ liệu mà nó sao chép

2

Sự khác biệt chính là memcpy()luôn sao chép số byte chính xác mà bạn chỉ định; strcpy(), mặt khác, sẽ sao chép cho đến khi nó đọc một byte NUL (hay còn gọi là 0), rồi dừng lại sau đó.


1

Vấn đề với chương trình thử nghiệm của bạn là chương trình printf()ngừng chèn đối số vào %skhi nó gặp phải dấu chấm dứt \0. Vì vậy, trong đầu ra của bạn, bạn có thể không nhận thấy, đã memcpy()sao chép các ký tự ch cũng như vậy.

Tôi đã thấy trong GNU glibc-2.24, rằng (đối với x86) strcpy()chỉ là các cuộc gọi memcpy(dest, src, strlen(src) + 1).


0

printf("%s",...) dừng in dữ liệu khi gặp null, vì vậy cả hai đầu ra đều giống nhau.

Đoạn mã sau phân biệt giữa strcpymemcpy:

#include<stdio.h>
#include<string.h>

int main()
{
    char s[5]={'s','a','\0','c','h'};
    char p[5];
    char t[5];
    int i;
    strcpy(p,s);
    memcpy(t,s,5);
    for(i=0;i<5;i++)
        printf("%c",p[i]);
        printf("\n");
    for(i=0;i<5;i++)
        printf("%c",t[i]);

    return 0;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.