A man is valued by his works, not his words!

Structure assignment and its pitfall in c language.

Jan 28 th , 2013 9:47 pm

There is a structure type defined as below:

2 3 4 5 struct __map_t { int code; char name[NAME_SIZE]; char *alias; }map_t;

If we want to assign map_t type variable struct2 to sturct1 , we usually have below 3 ways:

2 3 4 5 6 7 8 9 10 struct1.code = struct2.code; strncpy(struct1.name, struct2.name, NAME_SIZE); struct1.alias = struct2.alias; /* Way #2: memcpy the whole memory content of struct2 to struct1 */ memcpy(&struct1, &struct2, sizeof(struct1)); /* Way #3: straight assignment with '=' */ struct1 = struct2;

Consider above ways, most of programmer won’t use way #1, since it’s so stupid ways compare to other twos, only if we are defining an structure assignment function. So, what’s the difference between way #2 and way #3? And what’s the pitfall of the structure assignment once there is array or pointer member existed? Coming sections maybe helpful for your understanding.

The difference between ‘=’ straight assignment and memcpy

The struct1=struct2; notation is not only more concise , but also shorter and leaves more optimization opportunities to the compiler . The semantic meaning of = is an assignment, while memcpy just copies memory. That’s a huge difference in readability as well, although memcpy does the same in this case.

Copying by straight assignment is probably best, since it’s shorter, easier to read, and has a higher level of abstraction. Instead of saying (to the human reader of the code) “copy these bits from here to there”, and requiring the reader to think about the size argument to the copy, you’re just doing a straight assignment (“copy this value from here to here”). There can be no hesitation about whether or not the size is correct.

Consider that, above source code also has pitfall about the pointer alias, it will lead dangling pointer problem ( It will be introduced below section ). If we use straight structure assignment ‘=’ in C++, we can consider to overload the operator= function , that can dissolve the problem, and the structure assignment usage does not need to do any changes, but structure memcpy does not have such opportunity.

The pitfall of structure assignment:

Beware though, that copying structs that contain pointers to heap-allocated memory can be a bit dangerous, since by doing so you’re aliasing the pointer, and typically making it ambiguous who owns the pointer after the copying operation.

If the structures are of compatible types, yes, you can, with something like:

(dest_struct, source_struct, sizeof(dest_struct));

} The only thing you need to be aware of is that this is a shallow copy. In other words, if you have a char * pointing to a specific string, both structures will point to the same string.

And changing the contents of one of those string fields (the data that the char points to, not the char itself) will change the other as well. For these situations a “deep copy” is really the only choice, and that needs to go in a function. If you want a easy copy without having to manually do each field but with the added bonus of non-shallow string copies, use strdup:

2 (dest_struct, source_struct, sizeof (dest_struct)); dest_struct->strptr = strdup(source_struct->strptr);

This will copy the entire contents of the structure, then deep-copy the string, effectively giving a separate string to each structure. And, if your C implementation doesn’t have a strdup (it’s not part of the ISO standard), you have to allocate new memory for dest_struct pointer member, and copy the data to memory address.

Example of trap:

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include <stdlib.h> #include <string.h> #define NAME_SIZE 16 typedef struct _map_t { int code; char name[NAME_SIZE]; char *alias; } map_t; int main() { map_t a, b, c; /* initialize the a's members value */ a.code = 1024; snprintf(a.name, NAME_SIZE, "Controller SW3"); char *alias = "RNC&IPA"; a.alias = alias; /* assign the value via memcpy */ memcpy(&b, &a, sizeof(b)); /* assign the value via '=' */ c = a; return 0; }

Below diagram illustrates above source memory layout, if there is a pointer field member, either the straight assignment or memcpy , that will be alias of pointer to point same address. For example, b.alias and c.alias both points to address of a.alias . Once one of them free the pointed address, it will cause another pointer as dangling pointer. It’s dangerous!!

  • Recommend use straight assignment ‘=’ instead of memcpy.
  • If structure has pointer or array member, please consider the pointer alias problem, it will lead dangling pointer once incorrect use. Better way is implement structure assignment function in C, and overload the operator= function in C++.
  • stackoverflow.com: structure assignment or memcpy
  • stackoverflow.com: assign one struct to another in C
  • bytes.com: structures assignment
  • wikipedia: struct in C programming language

Understanding memcpy Behavior with Array and Pointer

Have you ever wondered why the two memcpy lines in your code snippet work exactly the same? In this article, we'll dive into the behavior of memcpy when working with arrays and pointers in C.

Address of Array and First Element

When you pass an array as an argument to a function or use it in an expression, it automatically converts to a pointer to its first element. This conversion is what allows the memcpy function to work with both buff and &buff[0] .

Unary & Operator

The unary & operator is an exception to the array-to-pointer conversion rule. It gives the address of its operand instead of converting an array to a pointer. So, when you write &buff , you get a pointer to the whole array.

Same Starting Location

The starting location of the first element of an array and the starting location of the array itself are the same. Therefore, &buff and buff have the same value, but different types. But, in both cases, data is copied to the same location.

Additionally, it's worth noting that the type difference becomes irrelevant in the context of memcpy . The first parameter of memcpy is declared as void * restrict , which means both &buff and buff are converted to the same type before the call.

In summary, the two memcpy lines work the same because the array buff automatically converts to a pointer to its first element, and the unary & operator gives the address of the whole array. The starting location of the first element and the array itself are the same, causing the data to be copied to the same location.

Next time you encounter a similar scenario, you'll understand why the two versions of memcpy have identical behavior!

Understanding memcpy Behavior with Array and Pointer

AOverflow.com

AOverflow.com Logo

Difference in assigning a char variable with memcpy() or directly inside a struct in c++?

What is the difference between using memcpy() or directly a pointer to declare the name variable inside the person struct in this code?

I know that internally an array is a pointer, but when doing it with a pointer it gives me a warning

In contrast, when performing with memcpy and with name[20], it does not give me any warning, what does the warning refer to?

c assignment operator vs memcpy

To know the difference we must start by clarifying concepts. In C++ everything has a type, including text literals. Thus, the literal "juan" has a type that is a constant 1 const char[5] formation of five characters. It's five characters times the four letters plus the string termination character and it's constant because it's a literal. When you write this instruction:

Being char * the type of persona1.nombre , the type const char[5] is implicitly converted to a string pointer ( const char * ) and normally c++ explicitly forbids pointing to read-only memory ( const ) with read-write pointers (which are not marked as const ) but in this case it does the turns a blind eye and displays an alarm for keeping a compatibility with c 2 . What that statement is doing is pointing a pointer to the start of the literal "juan" , so the assigned variable is a pointer (even if it's the wrong type).

If we generate an example code and examine its assembler, we see that the compiler does just that, an assignment:

After the operation, you will have two pointers pointing to the same place and a single copy of the data:

If, on the other hand, we make the call to memcpy we see that the compiler does, effectively, a function call:

After the operation you will have two pointers, pointing to different sites but with a copy of the data:

By the way, contrary to what your comment ( //sin puntero ) says, calling memcpy also uses pointers, the destination memory pointer and the source memory pointer; but also since you have not reserved space to copy the data in the destination memory, your program can fail at run time.

Once these differences have been explained, I advise you not to use character formations to save text, in C++ the object is used std::string , which is safer and easier to use:

Also note that in C++ structs are types in their own right, so they don't need a type definition ( type def inition ) to be treated as such:

1 Also known as array .

2 In C the type of character literals does not include const .

Web Analytics Made Easy - Statcounter

Memcpy vs assignment in C

c memcpy struct variable-assignment

Under what circumstances should I expect memcpys to outperform assignments on modern INTEL/AMD hardware? I am using GCC 4.2.x on a 32 bit Intel platform (but am interested in 64 bit as well).

Best Answer

You should never expect them outperform assignments. The reason is, the compiler will use memcpy anyway when it thinks it would be faster (if you use optimize flags). If not and if the structure is reasonable small that it fits into registers, direct register manipulation could be used which wouldn't require any memory access at all.

GCC has special block-move patterns internally that figure out when to directly change registers / memory cells, or when to use the memcpy function. Note when assigning the struct, the compiler knows at compile time how big the move is going to be, so it can unroll small copies (do a move n-times in row instead of looping) for instance. Note -mno-memcpy :

Who knows it better when to use memcpy than the compiler itself?

Related Solutions

Very fast memcpy for image processing.

Courtesy of William Chan and Google. 30-70% faster than memcpy in Microsoft Visual Studio 2005.

You may be able to optimize it further depending on your exact situation and any assumptions you are able to make.

You may also want to check out the memcpy source (memcpy.asm) and strip out its special case handling. It may be possible to optimise further!

JavaScript OR (||) variable assignment explanation

See short-circuit evaluation for the explanation. It's a common way of implementing these operators; it is not unique to JavaScript.

Related Topic

  • Bash – Command not found error in Bash variable assignment
  • Visual-studio – How to increase performance of memcpy
  • Memcpy() vs memmove()
  • Java – Why don’t Java’s +=, -=, *=, /= compound assignment operators require casting
  • C++ – In CMake, how can I test if the compiler is Clang
  • When __builtin_memcpy is replaced with libc’s memcpy
  • C++ – Poor memcpy Performance on Linux

Logo

  • Search in titles only Search in C only Search
  • Advanced Search

structure assignment vs memcpy

  • Latest Activity
  • Time All Time Today Last Week Last Month
  • Show All Discussions only Photos only Videos only Links only Polls only Events only

subramanian100in@yahoo.com, India

  • Runtime Protection
  • Continuous Monitoring
  • Threat Detection
  • Sternum Labs
  • Fundamentals
  • Regulation Learning Center
  • Video Series
  • Case Studies

SUGGESTED READ

IoT Security:

Learn about cyber threat protections for devices and networks.

Medical Device Regulations:

Unpack the strict regulations medical device manufacturers face.

Understand the challenges and security concerns around real-time operating systems (RTOS).

Learn more about Sternum

Get the latest

Join our team

  • Free Evaluation Kit

Experience all platform features

  • Book a demo

memcpy C Function – Syntax, Examples, and Security Best Practices

Igal Zeifman

Igal Zeifman

6  min read | min read | 23/04/2023

What is memcpy()

memcpy() is a standard function used in the C programming language to copy blocks of memory from one place to another. Its prototype is defined in the string.h header file as follows:

The memcpy() function copies the contents of a source buffer to a destination buffer, starting from the memory location pointed to by src , and continuing for n bytes. The areas of memory should not overlap, and the behavior is undefined if they do.

The function is commonly used in C programming for tasks such as copying the contents of one array to another, or for copying structures or other data types that are not handled by simple assignment. Using memcpy() is often preferred over a loop-based approach to copying memory, as it is generally faster and more efficient.

Common Use Cases for the memcpy() Function

The versatility of the memcpy() function makes it a go-to option for a variety of programming tasks involving strings, arrays, and pointers in the C programming language, for instance:

  • Strings: memcpy() is often used for tasks such as concatenation or copying substrings. For example, you could use memcpy to copy a portion of a source string to a dest buffer or to concatenate two strings together into a new buffer.
  • Arrays: memcpy() can be used to copy the contents of one array to another. This is often useful when working with large arrays that may be time-consuming to copy using a loop-based approach. memcpy can also be used to manipulate arrays by copying subsets of elements from one location to another.
  • Pointers: The memcpy() function enables the copying of the contents of one memory location to different places, even when the source and destination are not contiguous blocks of memory. This is useful when working with complex data structures or when copying data between non-contiguous memory spaces.

How memcpy() Works: Syntax and Code Example

The memcpy() function takes three arguments:

  • dest : a pointer to the destination buffer location where the data is to be copied.
  • src : a pointer to the source buffer from where the data is to be copied.
  • n : the number of copied bytes.

Here is a simple example of how it all comes together. The below code copies the content of src (the source buffer) to dest (the destination buffer). Note that this code uses the sizeof operator instead of n (the number of bytes to be copied), which allows the program to copy all of the bytes from the source buffer.

memcpy-output-example

memcpy Alternatives

Of course, memcpy() is not the only way to move memory blocks around in C. Here is a quick rundown of some alternatives:

memcpy vs. memmove

memcpy() and memmove() are both standard C-language library functions used to copy blocks of memory between different locations. The main difference between memcpy() and memmove() is in how they handle overlapping memory regions. When copying memory, memcpy assumes that the source and destination memory regions do not overlap, and will produce undefined behavior if they do. In contrast, memmove() is designed to handle overlapping memory regions and will copy the memory correctly regardless of whether the regions overlap or not.

In the example below the memcpy() function enables the copying of the substring “world!” from the str array to the buffer array. However, since the source and destination regions overlap, the function’s behavior is not defined, and the program may produce unexpected results.

The memmove() function does exactly the same, copying the substring to the buffer array, but it will be correctly handle the overlapping regions.

memcpy vs. strcpy

strcpy() is another standard C-language library function and (you guessed it) it’s also used to copy memory between locations. The main difference between it and memcpy() is the type of data they are designed to handle. Specifically, memcpy() is a low-level function that can copy any type of data, including non-character data types such as integers, floating-point numbers, and structures. In contrast, strcpy() is specifically designed to copy null-terminated character strings, and will produce undefined behavior if used with non-string data.

Another important difference between memcpy() and strcpy() is the way they handle the null terminator character. memcpy() does not add a null terminator to the copied data, so it is up to the programmer to ensure that the destination buffer is properly terminated. In contrast, strcpy() automatically adds a null terminator to the copied string, so the programmer does not need to explicitly add one.

The simple example below illustrates the difference between the two functions. In this example, memcpy is used to copy the contents of the source array to the buffer array. Since it does not add a null terminator, the programmer must manually add one to ensure that the copied string is properly terminated.

In contrast, the strcpy function is used to copy the same string to the buffer array, and automatically adds a null terminator to the end of the copied string.

Security Best Practices

memcpy() can be used securely if it is used with care. However, since it is a low-level function that allows direct memory access, it can be dangerous if used incorrectly.

There are two primary security concerns with memcpy() :

  • Buffer overflow vulnerabilities : If the destination buffer is too small to hold the copied data, the function can overwrite adjacent memory regions and cause undefined behavior, which could potentially be exploited by an attacker. To avoid this, it is essential to ensure that the dest buffer is sufficiently large to hold the copied data and to check that the size of the copied data does not exceed the size of the buffer.
  • Memory leaks:  If the function is used to copy sensitive information, such as passwords or cryptographic keys, and the memory is not properly cleared after use, an attacker may be able to access this information by reading the memory.

To avoid these security concerns, it is important to follow these best practices when using memcpy() :

  • Ensuring that the destination buffer has an adequate size to hold the copied data.
  • Checking the amount of data being copied to ensure it does not exceed the capacity of the buffer.
  • Avoiding the use of strcpy with non-string data types, since it can result in undefined behavior and potential security vulnerabilities.
  • Clearing the memory after use, especially if the data being copied is sensitive.
  • Using standard library functions like strncpy and memset that are designed to handle strings and memory operations safely, rather than manually writing code that accesses memory directly.

Deterministic Security for IoT with Sternum

The memcpy() function is a commonplace culprit behind many vulnerabilities in IoT/embedded devices.

Sternum’s patented EIV™ ( embedded integrity verification ) technology protects from these with runtime (RASP-like) protection that deterministically prevents all memory and code manipulation attempts, offering blanket protection from a broad range of software weaknesses (CWEs), including the ones related to improper use of memcpy() and other exploitable functions.

Embedding itself directly in the firmware code, EIV™ is agentless and connection agnostic. Operating at the bytecode level, it is also universally compatible with any IoT device or operating system ( RTOS , Linux, OpenWrt , Zephyr , Micirum, FreeRTOS, etc.) and has a low overhead of only 1-3%, even on legacy devices.

The runtime protection features are also augmented by (XDR-like) threat detection capabilities of Sternum’s Cloud platform, its AI-powered anomaly detection, and extended monitoring capabilities.

To learn more, check out these case studies of how this technology was used to:

– Help a Fortune 500 company catch memory leaks in pre-production (Zephyr device)

– Uncover buffer overflow vulnerabilities in 80,000 NAS devices

– Uncover buffer overflow vulnerability in a very popular smart plug device

Also check out the video below to see Sternum EIV™ in action, as it provides out-of-the-box mitigation of Ripple20 malware, used for memory corruption attacks.

JUMP TO SECTION

Take Sternum for a Test Drive with a Free Evaluation Kit

Take Sternum for a Test Drive with a Free Evaluation Kit

Enter data to download case study.

By submitting this form, you agree to our Privacy Policy.

Related articles

Top Linux Security Vulnerabilities and How to Prevent Them

Top Linux Security Vulnerabilities and How to Prevent Them

Lian Granot

Lian Granot

7  min read | 26/08/2024

Linux Security Pros and Cons and 7 Ways to Secure Linux Systems

Linux Security Pros and Cons and 7 Ways to Secure Linux Systems

11  min read | 12/08/2024

Getting Started with IoT Device Observability: What Should You Trace?

Getting Started with IoT Device Observability: What Should You Trace?

5  min read | 02/08/2024

Looking to learn more? Book a demo with our experts ►►

Lorem ipsum dolor sit amet.

  • IoT Security
  • Medical Device Regulation
  • Vulnerability Management
  • Keynote: The Hacker Perspective
  • Webinar: Medtronic Monitoring & Debugging

© Sternum 2024 · All rights reserved

Get the Reddit app

A subreddit for all questions related to programming in any language.

Should memcpy and the assignment operator (=) be interchangeable when reading/writing bytes to a void* or char* on the heap in c/c++?

I hope this question isn't to specific or inappropriately placed but I'm not sure where to ask and haven't been able to find any answers via Google. Also, sorry in advance but I can't share my code due to my professors academic integrity policy, but I hope that I've included enough detail to explain my question. My code is currently working (probably), I just am not sure why...

For context I'm working on a record based file manager for my Database Systems class and the project involves creating paged files that are read in 4096 byte pages, and then writing records to any page in the file that has enough space to contain it. Each page has a directory so that records stored on it can be accessed randomly instead of having to scan the entire page. The entries are at the begging of the page, free space is int he middle, and the directory is at the end.

Two of the elements of the page format are a slot count which describes how many records are on that page, and a free space offset value which points to exactly what it says, the beginning of free space on the page. These values are represented as shorts because they only need to be able to address 4096 bytes. The page itself is represented as just a chunk of memory 4096 bytes long in memory that I create with malloc(). Oftentimes it's cast to a char*. The free space offset is stored in the last 2 bytes , and the slot count is stored in the preceding two bytes

The issue I had was that I could store values in the page using memcpy but when pulling them back out they would be read as different values (often turning negative).

I would store values in the page as follows:

and I would retrieve them as follows:

I fixed (hopefully) the issue by changing the retrieval to this but it seems really clunky:

Now it seems to work, but whats killing me is that I don't know why? I thought I could address memory as an array and that the two retrieval methods did the same thing?

My assumption is either, the first method does something different regarding the endianness of the bytes in the data or it does some sort of sign extension that I don't want it to (wich is making my values go negative), but I have no clue if either of those are the correct reason the first method is broken. Can anyone explain how these are different or point me in the direction of a resource that can help me understand?

By continuing, you agree to our User Agreement and acknowledge that you understand the Privacy Policy .

Enter the 6-digit code from your authenticator app

You’ve set up two-factor authentication for this account.

Enter a 6-digit backup code

Create your username and password.

Reddit is anonymous, so your username is what you’ll go by here. Choose wisely—because once you get a name, you can’t change it.

Reset your password

Enter your email address or username and we’ll send you a link to reset your password

Check your inbox

An email with a link to reset your password was sent to the email address associated with your account

Choose a Reddit account to continue

c assignment operator vs memcpy

Forgot your password?

Please contact us if you have any trouble resetting your password.

🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Assignment vs Memcpy

c assignment operator vs memcpy

Quote: Original post by ToohrVyk Very interesting, and it does make sense: the presence of a constructor marks the object as non-POD, so the compiler generates a member-wise assignment operator, which in turn incurs an alignment property.

Stephen M. Webb Professional Free Software Developer

c assignment operator vs memcpy

This topic is closed to new replies.

Popular topics.

c assignment operator vs memcpy

Recommended Tutorials

Myopic Rhino

Reticulating splines

cppreference.com

Std:: memcpy.

(C++20)
(C++20)
(C++11)
(C++20)
(C++17)
(C++11)
(C++11)
Classes
Functions
Character manipulation
    
atolatoll (C++11)
strtoll (C++11)

strtoull (C++11)
strtodstrtold (C++11)
strtouimax (C++11)



* memcpy( void* dest, const void* src, count );

Copies count bytes from the object pointed to by src to the object pointed to by dest . Both objects are reinterpreted as arrays of unsigned char .

If the objects overlap, the behavior is undefined.

If either dest or src is an invalid or null pointer , the behavior is undefined, even if count is zero.

If the objects are potentially-overlapping or not TriviallyCopyable , the behavior of memcpy is not specified and may be undefined .

Parameters Return value Notes Example See also

[ edit ] Parameters

dest - pointer to the memory location to copy to
src - pointer to the memory location to copy from
count - number of bytes to copy

[ edit ] Return value

[ edit ] notes.

std::memcpy may be used to implicitly create objects in the destination buffer.

std::memcpy is meant to be the fastest library routine for memory-to-memory copy. It is usually more efficient than std::strcpy , which must scan the data it copies or std::memmove , which must take precautions to handle overlapping inputs.

Several C++ compilers transform suitable memory-copying loops to std::memcpy calls.

Where strict aliasing prohibits examining the same memory as values of two different types, std::memcpy may be used to convert the values.

[ edit ] Example

[ edit ] see also.

moves one buffer to another
(function)
fills a buffer with a character
(function)
copies a certain amount of wide characters between two non-overlapping arrays
(function)
copies characters
(public member function of )
copy_if (C++11) copies a range of elements to a new location
(function template)
copies a range of elements in backwards order
(function template)
checks if a type is trivially copyable
(class template)
for memcpy
  • Recent changes
  • Offline version
  • What links here
  • Related changes
  • Upload file
  • Special pages
  • Printable version
  • Permanent link
  • Page information
  • In other languages
  • This page was last modified on 25 October 2023, at 09:01.
  • This page has been accessed 1,962,862 times.
  • Privacy policy
  • About cppreference.com
  • Disclaimers

Powered by MediaWiki

  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Advertising & Talent Reach devs & technologists worldwide about your product, service or employer brand
  • OverflowAI GenAI features for Teams
  • OverflowAPI Train & fine-tune LLMs
  • Labs The future of collective knowledge sharing
  • About the company Visit the blog

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Get early access and see previews of new features.

Is it better to use std::memcpy() or std::copy() in terms to performance?

Is it better to use std::memcpy() as shown below, or is it better to use std::copy() in terms to performance? Why?

  • performance

A.R.M's user avatar

  • Note that char can be signed or unsigned, depending on the implementation. If the number of bytes can be >= 128, then use unsigned char for your byte arrays. (The (int *) cast would be safer as (unsigned int *) , too.) –  Dan Breslau Commented Jan 16, 2011 at 18:03
  • 14 Why aren't you using std::vector<char> ? Or since you say bits , std::bitset ? –  GManNickG Commented Jan 16, 2011 at 19:20
  • 2 Actually, could you please explain to me what (int*) copyMe->bits[0] does? –  user2138149 Commented Aug 25, 2015 at 21:38
  • 4 not sure why something that seems like such a mess with so little vital context provided was at +81, but hey. @user3728501 my guess is that the start of the buffer holds an int dictating its size, but that seems like a recipe for implementation-defined disaster, like so many other things here. –  underscore_d Commented Apr 12, 2016 at 19:22
  • 3 In fact, that (int *) cast is just pure undefined behaviour, not implementation-defined. Trying to do type-punning via a cast violates strict aliasing rules and hence is totally undefined by the Standard. (Also, in C++ although not C, you can't type-pun via a union either.) Pretty much the only exception is if you're converting to a variant of char* , but the allowance is not symmetrical. –  underscore_d Commented Mar 19, 2017 at 19:07

8 Answers 8

I'm going to go against the general wisdom here that std::copy will have a slight, almost imperceptible performance loss. I just did a test and found that to be untrue: I did notice a performance difference. However, the winner was std::copy .

I wrote a C++ SHA-2 implementation. In my test, I hash 5 strings using all four SHA-2 versions (224, 256, 384, 512), and I loop 300 times. I measure times using Boost.timer. That 300 loop counter is enough to completely stabilize my results. I ran the test 5 times each, alternating between the memcpy version and the std::copy version. My code takes advantage of grabbing data in as large of chunks as possible (many other implementations operate with char / char * , whereas I operate with T / T * (where T is the largest type in the user's implementation that has correct overflow behavior), so fast memory access on the largest types I can is central to the performance of my algorithm. These are my results:

Time (in seconds) to complete run of SHA-2 tests

Total average increase in speed of std::copy over memcpy: 2.99%

My compiler is gcc 4.6.3 on Fedora 16 x86_64. My optimization flags are -Ofast -march=native -funsafe-loop-optimizations .

Code for my SHA-2 implementations.

I decided to run a test on my MD5 implementation as well. The results were much less stable, so I decided to do 10 runs. However, after my first few attempts, I got results that varied wildly from one run to the next, so I'm guessing there was some sort of OS activity going on. I decided to start over.

Same compiler settings and flags. There is only one version of MD5, and it's faster than SHA-2, so I did 3000 loops on a similar set of 5 test strings.

These are my final 10 results:

Time (in seconds) to complete run of MD5 tests

Total average decrease in speed of std::copy over memcpy: 0.11%

Code for my MD5 implementation

These results suggest that there is some optimization that std::copy used in my SHA-2 tests that std::copy could not use in my MD5 tests. In the SHA-2 tests, both arrays were created in the same function that called std::copy / memcpy . In my MD5 tests, one of the arrays was passed in to the function as a function parameter.

I did a little bit more testing to see what I could do to make std::copy faster again. The answer turned out to be simple: turn on link time optimization. These are my results with LTO turned on (option -flto in gcc):

Time (in seconds) to complete run of MD5 tests with -flto

Total average increase in speed of std::copy over memcpy: 0.72%

In summary, there does not appear to be a performance penalty for using std::copy . In fact, there appears to be a performance gain.

Explanation of results

So why might std::copy give a performance boost?

First, I would not expect it to be slower for any implementation, as long as the optimization of inlining is turned on. All compilers inline aggressively; it is possibly the most important optimization because it enables so many other optimizations. std::copy can (and I suspect all real world implementations do) detect that the arguments are trivially copyable and that memory is laid out sequentially. This means that in the worst case, when memcpy is legal, std::copy should perform no worse. The trivial implementation of std::copy that defers to memcpy should meet your compiler's criteria of "always inline this when optimizing for speed or size".

However, std::copy also keeps more of its information. When you call std::copy , the function keeps the types intact. memcpy operates on void * , which discards almost all useful information. For instance, if I pass in an array of std::uint64_t , the compiler or library implementer may be able to take advantage of 64-bit alignment with std::copy , but it may be more difficult to do so with memcpy . Many implementations of algorithms like this work by first working on the unaligned portion at the start of the range, then the aligned portion, then the unaligned portion at the end. If it is all guaranteed to be aligned, then the code becomes simpler and faster, and easier for the branch predictor in your processor to get correct.

Premature optimization?

std::copy is in an interesting position. I expect it to never be slower than memcpy and sometimes faster with any modern optimizing compiler. Moreover, anything that you can memcpy , you can std::copy . memcpy does not allow any overlap in the buffers, whereas std::copy supports overlap in one direction (with std::copy_backward for the other direction of overlap). memcpy only works on pointers, std::copy works on any iterators ( std::map , std::vector , std::deque , or my own custom type). In other words, you should just use std::copy when you need to copy chunks of data around.

Dev Null's user avatar

  • 53 I want to emphasize that this doesn't mean that std::copy is 2.99% or 0.72% or -0.11% faster than memcpy , these times are for the entire program to execute. However, I generally feel that benchmarks in real code are more useful than benchmarks in fake code. My entire program got that change in execution speed. The real effects of just the two copying schemes will have greater differences than shown here when taken in isolation, but this shows that they can have measurable differences in actual code. –  David Stone Commented Apr 3, 2012 at 17:31
  • 3 I want to disagree with your findings, but results are results :/. However one question (I know it was a long time ago and you don't remember research, so just comment the way you think), you probably didn't look into assembly code; –  ST3 Commented Jan 6, 2015 at 9:17
  • 2 In my opinion memcpy and std::copy has different implementations, so in some cases compiler optimizes surrounding code and actual memory copy code as a one integral piece of code. It other words sometimes one is better then another and even in other words, deciding which to uses is premature or even stupid optimization, because in every situation you have to do new research and, what is more, programs are usually being developed, so after some minor changes advantage of function over other may be lost. –  ST3 Commented Jan 6, 2015 at 9:18
  • 4 @ST3: I would imagine that in the worst case, std::copy is a trivial inline function that just calls memcpy when it is legal. Basic inlining would eliminate any negative performance difference. I will update the post with a bit of an explanation of why std::copy might be faster. –  David Stone Commented Jan 8, 2015 at 2:21
  • 12 Very informative analysis. Re Total average decrease in speed of std::copy over memcpy: 0.11% , whilst the number is correct, the results aren't statistically significant. A 95% confidence interval for the difference in means is (-0.013s, 0.025), which includes zero. As you pointed out there was variation from other sources and with your data, you'd probably say the performance is the same. For reference, the other two results are statistically significant -- the chances you'd see a difference in times this extreme by chance are about 1 in 100 million (first) and 1 in 20,000 (last). –  TooTone Commented Mar 11, 2016 at 13:24

All compilers I know will replace a simple std::copy with a memcpy when it is appropriate, or even better, vectorize the copy so that it would be even faster than a memcpy .

In any case: profile and find out yourself. Different compilers will do different things, and it's quite possible it won't do exactly what you ask.

See this presentation on compiler optimisations (pdf).

Here's what GCC does for a simple std::copy of a POD type.

Here's the disassembly (with only -O optimisation), showing the call to memmove :

If you change the function signature to

then the memmove becomes a memcpy for a slight performance improvement. Note that memcpy itself will be heavily vectorised.

Peter Alexander's user avatar

  • 2 How can I do profiling. What tool to use (in windows and linux)? –  user576670 Commented Jan 16, 2011 at 18:00
  • 7 @Konrad, you're correct. But memmove shouldn't be faster - rather, it should be slighter slower because it has to take into account the possibility that the two data ranges overlap. I think std::copy permits overlapping data, and so it has to call memmove . –  Charles Salvia Commented Jan 16, 2011 at 18:04
  • 2 @Konrad: If memmove was always faster than memcpy, then memcpy would call memmove. What std::copy actually might dispatch to (if anything) is implementation-defined, so it's not useful to mention specifics without mentioning implementation. –  Fred Nurk Commented Jan 16, 2011 at 18:04
  • 1 Although, a simple program to reproduce this behavior, compiled with -O3 under GCC shows me a memcpy . It leads me to believe GCC checks whether there's memory overlap. –  jweyrich Commented Jan 16, 2011 at 18:31
  • 1 @Konrad: standard std::copy allows overlap in one direction but not the other. The beginning of the output can't lie within the input range, but the beginning of the input is allowed to lie within the output range. This is a little odd, because the order of assignments is defined, and a call might be UB even though the effect of those assignments, in that order, is defined. But I suppose the restriction allows vectorization optimizations. –  Steve Jessop Commented Jan 16, 2011 at 20:58

Always use std::copy because memcpy is limited to only C-style POD structures, and the compiler will likely replace calls to std::copy with memcpy if the targets are in fact POD.

Plus, std::copy can be used with many iterator types, not just pointers. std::copy is more flexible for no performance loss and is the clear winner.

masoud's user avatar

  • Why should you wanna copy around iterators? –  Atmocreations Commented Oct 14, 2011 at 15:41
  • 3 You're not copying the iterators, but rather the range defined by two iterators. For instance, std::copy(container.begin(), container.end(), destination); will copy the contents of container (everything between begin and end ) into the buffer indicated by destination . std::copy doesn't require shenanigans like &*container.begin() or &container.back() + 1 . –  David Stone Commented Apr 26, 2012 at 17:13

In theory, memcpy might have a slight , imperceptible , infinitesimal , performance advantage, only because it doesn't have the same requirements as std::copy . From the man page of memcpy :

To avoid overflows, the size of the arrays pointed by both the destination and source parameters, shall be at least num bytes, and should not overlap (for overlapping memory blocks, memmove is a safer approach).

In other words, memcpy can ignore the possibility of overlapping data. (Passing overlapping arrays to memcpy is undefined behavior.) So memcpy doesn't need to explicitly check for this condition, whereas std::copy can be used as long as the OutputIterator parameter is not in the source range. Note this is not the same as saying that the source range and destination range can't overlap.

So since std::copy has somewhat different requirements, in theory it should be slightly (with an extreme emphasis on slightly ) slower, since it probably will check for overlapping C-arrays, or else delegate the copying of C-arrays to memmove , which needs to perform the check. But in practice, you (and most profilers) probably won't even detect any difference.

Of course, if you're not working with PODs , you can't use memcpy anyway.

Charles Salvia's user avatar

  • 7 This is true for std::copy<char> . But std::copy<int> can assume that its inputs are int-aligned. That will make a far bigger difference, because it affects every element. Overlap is a one-time check. –  MSalters Commented Jan 17, 2011 at 8:39
  • 2 @MSalters, true, but most implementations of memcpy I've seen check for alignment and attempt to copy words rather than byte by byte. –  Charles Salvia Commented Apr 28, 2012 at 8:13
  • 1 std::copy() can ignore overlapping memory, too. If you want to support overlapping memory, you have to write the logic yourself to call std::reverse_copy() in the appropriate situations. –  Cygon Commented Jun 6, 2012 at 11:23
  • 2 There is an opposite argument that can be made: when going through memcpy interface it loses the alignment information. Hence, memcpy has to do alignment checks at run-time to handle unaligned beginnings and ends. Those checks may be cheap but they are not free. Whereas std::copy can avoid these checks and vectorize. Also, the compiler may prove that source and destination arrays do not overlap and again vectorize without the user having to choose between memcpy and memmove . –  Maxim Egorushkin Commented Jan 12, 2016 at 15:42

My rule is simple. If you are using C++ prefer C++ libraries and not C :)

UmmaGumma's user avatar

  • 47 C++ was explicitly designed to allow using C libraries. This was not an accident. It is often better to use std::copy than memcpy in C++, but this has nothing to do with which one is C, and that kind of argument is usually the wrong approach. –  Fred Nurk Commented Jan 16, 2011 at 18:06
  • 4 @FredNurk Usually you want to avoid weak area of C where C++ provide a safer alternative. –  Phil1970 Commented Apr 18, 2017 at 23:13
  • @Phil1970 I'm not sure that C++ is much safer in this case. We still have to pass valid iterators that don't overrun, etc. I guess being able to use std::end(c_arr) instead of c_arr + i_hope_this_is_the_right_number_of elements is safer? and perhaps more importantly, clearer. And that'd be the point I emphasise in this specific case: std::copy() is more idiomatic, more maintainable if the types of the iterators changes later, leads to clearer syntax, etc. –  underscore_d Commented Jan 2, 2018 at 18:08
  • 2 @underscore_d std::copy is safer because it correctly copies the passed data in case they are not POD-types. memcpy will happily copy a std::string object to a new representation byte by byte. –  Jens Commented Jan 17, 2019 at 9:05

Just a minor addition: The speed difference between memcpy() and std::copy() can vary quite a bit depending on if optimizations are enabled or disabled. With g++ 6.2.0 and without optimizations memcpy() clearly wins:

When optimizations are enabled ( -O3 ), everything looks pretty much the same again:

The bigger the array the less noticeable the effect gets, but even at N=1000 memcpy() is about twice as fast when optimizations aren't enabled.

Source code (requires Google Benchmark):

Grumbel's user avatar

  • 22 Measuring performance with optimizations disabled is... well... pretty much pointless... If you are interested in performance you won't compile without optimizations. –  bolov Commented Oct 18, 2016 at 13:32
  • 6 @bolov Not always. A relatively fast program under debug is in some cases important to have. –  Acorn Commented Jul 11, 2019 at 15:25
  • @bolov I used to think the same, but actually games running in debug mode can be heavily impacted by this. Well, maybe there are other solutions like inlining in debug mode... but that is a use case already. –  Germán Diago Commented Mar 31, 2021 at 12:08
  • Measuring speed without optimization? It is like trying to time muscle cars' speed while they are being pushed by hands. –  stackoverblown Commented May 20 at 15:01

If you really need maximum copying performance (which you might not), use neither of them .

There's a lot that can be done to optimize memory copying - even more if you're willing to use multiple threads/cores for it. See, for example:

What's missing/sub-optimal in this memcpy implementation?

both the question and some of the answers have suggested implementations or links to implementations.

einpoklum's user avatar

  • 7 pedant mode: with the usual caveat that " use neither of them " means if you have proven that you have a highly specific situation/requirement for which neither Standard function provided by your implementation is fast enough ; otherwise, my usual concern is that people who haven't proven that get sidetracked on prematurely optimising copying code instead of the usually more useful parts of their program. –  underscore_d Commented Jan 2, 2018 at 18:22

Profiling shows that statement: std::copy() is always as fast as memcpy() or faster is false.

HP-Compaq-dx7500-Microtower 3.13.0-24-generic #47-Ubuntu SMP Fri May 2 23:30:00 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux. gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2

The code (language: c++):

g++ -O0 -o test_stdcopy test_stdcopy.cpp memcpy() profile: main:21: now:1422969084:04859 elapsed:2650 us std::copy() profile: main:27: now:1422969084:04862 elapsed:2745 us memcpy() elapsed 44 s std::copy() elapsed 45 s g++ -O3 -o test_stdcopy test_stdcopy.cpp memcpy() profile: main:21: now:1422969601:04939 elapsed:2385 us std::copy() profile: main:28: now:1422969601:04941 elapsed:2690 us memcpy() elapsed 27 s std::copy() elapsed 43 s

Red Alert pointed out that the code uses memcpy from array to array and std::copy from array to vector. That coud be a reason for faster memcpy.

Since there is

v.reserve(sizeof(arr1));

there shall be no difference in copy to vector or array.

The code is fixed to use array for both cases. memcpy still faster:

imatveev13's user avatar

  • 2 wrong, your profiling shows that copying into an array is faster than copying into a vector. Off topic. –  Red Alert Commented Feb 13, 2015 at 1:58
  • I could be wrong, but in your corrected example, with memcpy, aren't you copying arr2 into arr1, while with std::copy, you are copying arr1 into arr2?... What you could do is to make multiple, alternating experiments (once a batch of memcpy, once a batch of std::copy, then back again with memcopy, etc., multiple times.). Then, I would use clock() instead of time(), because who knows what your PC could be doing in addition to that program. Just my two cents, though... :-) –  paercebal Commented Apr 17, 2015 at 8:55
  • 9 So, switching std::copy from a vector to an array somehow made memcpy take nearly twice as long? This data is highly suspect. I compiled your code using gcc with -O3, and the generated assembly is the same for both loops. So any difference in time you observe on your machine is only incidental. –  Red Alert Commented May 6, 2015 at 0:46

Your Answer

Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more

Sign up or log in

Post as a guest.

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .

Not the answer you're looking for? Browse other questions tagged c++ performance or ask your own question .

  • The Overflow Blog
  • The evolution of full stack engineers
  • One of the best ways to get value for AI coding tools: generating tests
  • Featured on Meta
  • Join Stack Overflow’s CEO and me for the first Stack IRL Community Event in...
  • User activation: Learnings and opportunities
  • Staging Ground Reviewer Motivation
  • What does a new user need in a homepage experience on Stack Overflow?

Hot Network Questions

  • Is the closest diagonal state to a given state always the dephased original state?
  • What's wrong with this solution?
  • What came of the Trump campaign's complaint to the FEC that Harris 'stole' (or at least illegally received) Biden's funding?
  • When deleting attribute from GDB file all the fields in the remaining attributes get deleted as well in QGIS
  • Why do so many great Tzaddikim die so young?
  • Was using an older version of a legal card from a nonlegal set ever not legal?
  • Use other units than point for arraycolsep
  • Paying a parking fine when I don't trust the recipient
  • How can I format a partition in a mapper device?
  • How did NASA know figure out when and where the Apollo capsule would touch down on the ocean?
  • Does any row of Pascal's triangle contain a Pythagorean triple?
  • How can I support a closet rod where there's no shelf?
  • jq - ip addr show in tabular format
  • Navigating career options after a disastrous PhD performance and a disappointed advisor?
  • How to prove that the Greek cross tiles the plane?
  • NSolve uses all CPU resources
  • How do elected politicians get away with not giving straight answers?
  • Can anyone ID this bike? NSW, Australia
  • Best memory / storage solution for high read / write throughput application(s)?
  • How can a microcontroller (such as an Arduino Uno) that requires 7-21V input voltage be powered via USB-B which can only run 5V?
  • Remove spaces from the 3rd line onwards in a file on linux
  • What is a natural-sounding verb form for the word dorveille?
  • Why is so much of likelihood theory focused on solving the score function equation?
  • Big Transition of Binary Counting in perspective of IEEE754 floating point

c assignment operator vs memcpy

IMAGES

  1. memcpy() function

    c assignment operator vs memcpy

  2. What is assignment operator in C with example?

    c assignment operator vs memcpy

  3. Operators in C

    c assignment operator vs memcpy

  4. Assignment operator

    c assignment operator vs memcpy

  5. Opérateurs en C++

    c assignment operator vs memcpy

  6. Memcpy vs memmove in c

    c assignment operator vs memcpy

VIDEO

  1. NPTEL Problem Solving through Programming in C ASSIGNMENT 6 ANSWERS 2024

  2. NPTEL Problem Solving Through Programming in C Week 0 Assignment Solution July 2024 |IIT Kharagpur

  3. NPTEL Problem Solving through Programming in C ASSIGNMENT 1 Week 1 Explanation || 2024||july

  4. Mega Castlevania IV port to the Sega Mega Drive/Sega Genesis

  5. Assignment Operator in C Programming

  6. Voltage Fighter Gowcaizer

COMMENTS

  1. struct

    Note when assigning the struct, the compiler knows at compile time how big the move is going to be, so it can unroll small copies (do a move n-times in row instead of looping) for instance. Note -mno-memcpy: -mmemcpy. -mno-memcpy. Force (do not force) the use of "memcpy()" for non-trivial block moves. The default is -mno-memcpy, which allows ...

  2. memcpy vs assignment in C -- should be memmove?

    o->i = *i; struct outer o; // assign a bunch of fields in o->i... frob(&o.i, o); return 0; If gcc decides to replace that assignment with memcpy, then it's an invalid call because the source and dest overlap. Obviously, if I change the assignment statement in frob to call memmove instead, then the problem goes away.

  3. memcpy() or assign? : r/C_Programming

    And don't worry about performance: memcpy () gets inlined by the compiler for small sizes and does generate a single MOV instruction when it's possible (e.g. copying 4 or 8 bytes). For bigger structs, memcpy () and val = *ptr are still identical because, val = *ptr actually emits code just calling memcpy ().

  4. What is the name of this concept

    Cats_and_Shit. •. I think you could say that the assignment operator is parametrically polymorphic, while memcpy uses subtyping. Parametric polymorphism is when an operation is defined abstractly such that works on any type (or any type with certain qualities); for assignment in C that is everything except arrays.

  5. Structure Assignment and Its Pitfall in C Language

    Recommend use straight assignment '=' instead of memcpy. If structure has pointer or array member, please consider the pointer alias problem, it will lead dangling pointer once incorrect use. Better way is implement structure assignment function in C, and overload the operator= function in C++. Reference:

  6. Understanding memcpy Behavior with Array and Pointer

    The first parameter of memcpy is declared as void * restrict, which means both &buff and buff are converted to the same type before the call. Conclusion. In summary, the two memcpy lines work the same because the array buff automatically converts to a pointer to its first element, and the unary & operator gives the address of the whole array ...

  7. Difference in assigning a char variable with memcpy() or directly

    To know the difference we must start by clarifying concepts. In C++ everything has a type, including text literals. Thus, the literal "juan"has a type that is a constant 1 const char[5] formation of five characters. It's five characters times the four letters plus the string termination character and it's constant because it's a literal.

  8. Memcpy vs assignment in C

    Best Answer. You should never expect them outperform assignments. The reason is, the compiler will use memcpy anyway when it thinks it would be faster (if you use optimize flags). If not and if the structure is reasonable small that it fits into registers, direct register manipulation could be used which wouldn't require any memory access at all.

  9. structure assignment vs memcpy

    Simply assign one object to another with the assignment operator. Structure assignments have been supported since C90. Of course if you only want to assign some members of a struct object to another, then you'll have to do it manually. Using memcpy is not usually necessary, since the language directly supports copying structures.

  10. memcpy C Function

    What is memcpy() memcpy() is a standard function used in the C programming language to copy blocks of memory from one place to another. Its prototype is defined in the string.h header file as follows:. void *memcpy(void *dest, const void *src, size_t n); The memcpy() function copies the contents of a source buffer to a destination buffer, starting from the memory location pointed to by src ...

  11. Should memcpy and the assignment operator (=) be ...

    Should memcpy and the assignment operator (=) be interchangeable when reading/writing bytes to a void* or char* on the heap in c/c++? I hope this question isn't to specific or inappropriately placed but I'm not sure where to ask and haven't been able to find any answers via Google. Also, sorry in advance but I can't share my code due to my ...

  12. Assignment vs Memcpy

    return 0; when i use the default assignment operator of the Test struct, the execution time is around 6600 milliseconds, but when i overload the assignment operator use memcpy with the size of the block to copy being known at compile time, the same program executes at around 3800 milliseconds.

  13. std::memcpy

    Return value. dest [] Notestd::memcpy may be used to implicitly create objects in the destination buffer.. std::memcpy is meant to be the fastest library routine for memory-to-memory copy. It is usually more efficient than std::strcpy, which must scan the data it copies or std::memmove, which must take precautions to handle overlapping inputs.. Several C++ compilers transform suitable memory ...

  14. c++

    One difference is that with memcpy the operands are not allowed to overlap, and the compiler knows that (__builtin_memcpy). With the first function the compiler itself has to prove that p doesn't point to one of the char members of x .

  15. Why does the copy constructor and copy assignment operator call `memcpy

    On the contrary,i think the outputs after "===" are right.I can completly understand it.But i can't undertand the outputs before "===".I would reedit the code to avoid the misunderstanding.I think it should call the user defined constructor EntityId_t(int id) and movement assignment operator,

  16. c++

    Yes of course, though memory allocated with new is taken from the "free store" it is still just in the application memory address space. memset and memcpy simply take address parameters for a source and destination, and these parameters can technically be to any address in your application's address space.

  17. c++

    The implicitly-defined copy assignment operator for a non-union class X performs memberwise copy assignment of its subobjects. The direct base classes of X are assigned first, in the order of their declaration in the base-specifier-list, and then the immediate non-static data members of X are assigned, in the order in which they were declared ...

  18. c++

    following the c++ 11 standard i suppose that g++ implicitly uses a member-wise copy whenever an assignment between two objects is done. Surprisingly I noticed that contrary to the standard, g++ seems to invoke a memcpy sized at the actual size of the object. Here below a snippet of what I meant.

  19. c++

    std::copy () can ignore overlapping memory, too. If you want to support overlapping memory, you have to write the logic yourself to call std::reverse_copy () in the appropriate situations. There is an opposite argument that can be made: when going through memcpy interface it loses the alignment information.