memcpy(3)

๐Ÿ’– memcpy(3) โ€” the memory-copy bestie ๐Ÿ’–

okay so we're doing memcpy, and honestly? iconic. this is the girl who moves your bytes from one place to another and does it FAST. she's in the Library Functions Manual and she lives in the Standard C library (libc, -lc). she's everywhere. you've used her a thousand times. let's get into it ๐Ÿซถ


โœจ NAME โœจ

memcpy โ€” memory copy. that's it. that's the whole job. and she ATE. ๐Ÿ’…


๐Ÿ“š LIBRARY ๐Ÿ“š

Standard C library (libc, -lc)

like yeah bestie she's standard, she's built in, she's not going anywhere. skip the -lm nonsense, this is the real deal. โœจ


๐ŸŽ€ SYNOPSIS ๐ŸŽ€

#include <string.h>  // see memory.h(3head)

and the signature, verbatim, exactly as written:

void *memcpy(size_t n;
             void dest[restrict n], const void src[restrict n],
             size_t n);

okay yes the header comment sends you to memory.h(3head), go look, we don't gatekeep here ๐ŸŒธ


๐Ÿ’ซ DESCRIPTION ๐Ÿ’ซ

so here's the tea. memcpy() copies n bytes from memory area src to memory area dest. that's it! that's her job! bytes go in one end, bytes come out the other end, and they're the same bytes ๐Ÿ’–

but. and this is the big but, the one your CS professor screamed about. the memory areas must not overlap. like, at all. not even a little. not even for one byte.

if your areas DO overlap? you do not call memcpy(). you call memmove(3) instead, because memmove(3) is the bestie who actually checks and handles it. memcpy() is the fast girl who assumes you know what you're doing. respect her boundaries, babe. ๐Ÿฆ‹


๐Ÿซถ RETURN VALUE ๐Ÿซถ

memcpy() returns a pointer to dest. she hands you back the destination like "here you go bestie, she's all yours" ๐Ÿ˜ญ๐Ÿ’œ


๐ŸŒˆ ATTRIBUTES ๐ŸŒˆ

for the deets on what all these terms even mean, hit up attributes(7). (that's a whole other man page, go read it, i'll wait ๐Ÿ’…)

here's the chart, but make it a vibe:

  • memcpy() โ€” Thread safety: MT-Safe

that's it! MT-Safe! she's multithread safe! she's not out here corrupting your threads, she knows what she's doing, she's got main character energy in every thread. slay. ๐Ÿ‘‘


โญ STANDARDS โญ

C11, POSIX.1-2008.

she's officially official. certified. no cap. ๐ŸŽ€


๐Ÿงš HISTORY ๐Ÿงš

POSIX.1-2001, C89, SVr4, 4.3BSD.

she's been around. she's seen things. she's a legacy icon and she's still the most-used function in your codebase. that's longevity bestie. ๐Ÿ•ฐ๏ธโœจ


๐Ÿ’€ CAVEATS ๐Ÿ’€

okay sit down. this is the part that's giving lore.

so failing to observe the requirement that the memory areas do not overlap has been the source of significant bugs. significant. as in, real production outages, real 3am pager duty, real "why is my data garbled" energy. ๐Ÿ˜ญ

(POSIX and the C standards are explicit that employing memcpy() with overlapping areas produces undefined behavior. undefined. as in, anything can happen. no promises. no take-backs. ๐Ÿ’€)

most notably โ€” and this is the drama โ€” in glibc 2.13 a performance optimization of memcpy() on some platforms (including x86-64) included changing the order in which bytes were copied from src to dest.

and this change revealed breakages in a number of applications that performed copying with overlapping areas. ๐Ÿ˜ณ

here's why that's so juicy: under the previous implementation, the order in which the bytes were copied had fortuitously hidden the bug โ€” it just happened to work! โ€” which was revealed when the copying order was reversed. like, the bug was always there, the old code was just covering for it. the way that a refactor can expose a decade of sloppy code is honestly kind of iconic ๐Ÿ’…

so what did they do? in glibc 2.14, a versioned symbol was added so that old binaries (i.e., those linked against glibc versions earlier than 2.14) employed a memcpy() implementation that safely handles the overlapping buffers case โ€” by providing an "older" memcpy() implementation that was aliased to memmove(3).

so if your binary is old, you get the safe one. if it's new, you get the fast one and you're on your own. respect the versioning, it's doing a lot of heavy lifting. ๐Ÿ‘‘

fr fr: do not pass overlapping buffers to memcpy(). if they overlap, that's memmove(3). do not test fate. do not "but it worked on my machine". it did NOT work, it just hadn't been caught yet. ๐Ÿ’€

๐Ÿ“ SEE ALSO ๐Ÿ“

  • memory.h(3head) โ€” the header bestie who spilled the tea
  • memmove(3) โ€” the safe one, the overlap handler, the responsible queen
  • mempcpy(3) โ€” memcpy() but she hands you back the end pointer instead, icon behavior
  • wmemcpy(3) โ€” same energy, wide characters, multilingual slay ๐ŸŒˆ

๐ŸŒธ FINAL VIBE CHECK ๐ŸŒธ

that's the page bestie! she's a one-job icon: copy n bytes, don't overlap, return dest. ๐ŸŽ€๐Ÿ’–

and a lil' sign-off for the credits: this was Linux man-pages version 6.20, dated 2026-08-10. shoutout to the whole man-pages crew, they really do keep us fed ๐Ÿซถโœจ

now go forth and memcpy() responsibly. periodt. ๐Ÿ’…๐Ÿ‘‘

๐Ÿ“ฆ where this page comes from
  • arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
  • nixpkgs unstable: man-pages 6.20
  • ๐Ÿ“œ the page's license: Linux-man-pages-copyleft
  • ๐Ÿ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms