سؤال
ماهو الفرق بين memcpy()
و strcpy()
؟ حاولت العثور عليه بمساعدة البرنامج ولكن كلاهما يعطي نفس الإخراج.
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;
}
انتاج |
sachin p is [sa], t is [sa]
المحلول
ما يمكن فعله لرؤية هذا التأثير
تجميع وتشغيل هذا الرمز:
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);
}
سوف ينتج هذا المخرج:
73 61 00 63 68 sa ch
73 61 00 00 00 sa
يمكنك أن ترى أنه تم نسخ "CH" memcpy()
, ، لكن لا strcpy()
.
نصائح أخرى
strcpy
يتوقف عندما يواجه نول ('\0'
) حرف، memcpy
لا. أنت لا ترى التأثير هنا ، %s
في printf يتوقف أيضا في نول.
strcpy
ينتهي عندما يتم العثور على Terminator الفارغ من السلسلة المصدر. memcpy
يتطلب تمرير معلمة الحجم. في الحالة التي قدمتها printf
يتوقف البيان بعد العثور على Terminator NULL لكلا صفيفات الأحرف ، ومع ذلك ستجد t[3]
و t[4]
لقد نسخت البيانات فيها أيضًا.
strcpy
نسخ الحرف من مصدر إلى الوجهة واحدة تلو الأخرى حتى تجد شخصية فارغة أو ' 0' في المصدر.
while((*dst++) = (*src++));
بينما memcpy
نسخ البيانات (وليس الحرف) من مصدر إلى الوجهة من حجم معين ، بغض النظر عن البيانات في المصدر.
memcpy
يجب استخدامه إذا كنت تعرف جيدًا أن هذا المصدر يحتوي على غير الشخصية. بالنسبة للبيانات المشفرة أو البيانات الثنائية ، تعد Memcpy طريقة مثالية للذهاب.
strcpy
تم إهماله ، لذا استخدم strncpy
.
بسبب الشخصية الفارغة في الخاص بك s
سلسلة ، printf
لن تظهر أي شيء يتجاوز ذلك. الفرق بين p
و t
سيكون في الشخصيات 4 و 5. p
لن يكون لها أي (سيكونون القمامة) و t
سوف يكون 'c'
و 'h'
.
- اختلاف السلوك:
strcpy
يتوقف عندما يواجه أNULL
أو'\0'
- فرق الأداء:
memcpy
عادة ما يكون أكثر كفاءة منstrcpy
, ، التي تقوم دائمًا بمسح البيانات التي تقوم بنسخها
الفرق الرئيسي هو ذلك memcpy()
يقوم دائمًا بنسخ العدد الدقيق للبايتات التي تحددها ؛ strcpy()
, ، من ناحية أخرى ، سوف نسخ حتى يقرأ بايت (ويعرف أيضًا باسم 0) ، ثم توقف بعد ذلك.
المشكلة في برنامج الاختبار الخاص بك هي أن printf()
يتوقف عن إدخال الحجة في %s
, ، عندما تواجه نهاية فارغة \0
. لذلك في إخراجك ربما لم تلاحظ ذلك ، ذلك memcpy()
نسخ الشخصيات c
و h
كذلك.
لقد رأيت في GNU glibc-2.24
, ، هذا (ل x86) strcpy()
فقط مكالمات memcpy(dest, src, strlen(src) + 1)
.