memcpy(), what should the value of the size parameter be?

前端 未结 12 2154
灰色年华
灰色年华 2020-12-09 09:36

I want to copy an int array to another int array. They use the same define for length so they\'ll always be of the same length.

What are the pros/cons of the followi

相关标签:
12条回答
  • 2020-12-09 10:06

    If dst was allocated from the heap (using malloc for example) the second solution will not work. sizeof(dst) will only work when it is know to the compiler. For example, the following example will fail as sizeof(dst) will be equal to the sizeof a pointer (4-8 bytes.)

    #define ARRAY_LENGTH 10
    int *dst;
    
    dst = malloc(ARRAY_LENGTH*sizeof(int));
    memcpy(dst, src, sizeof(dst)); // sizeof dst in this case would be 4 bytes on 32 bit system
    

    This code segment will work every time:

    #define ARRAY_LENGTH 10
    int *dst;
    
    dst = malloc(ARRAY_LENGTH*sizeof(int));
    memcpy(dst, src, ARRAY_LENGTH*sizeof(int)); // sizeof would be 40 bytes
    
    0 讨论(0)
  • 2020-12-09 10:06

    memcpy(), what should the value of the size parameter be?

    It should be the minimum between the size of the source buffer and the size of the destination buffer.

    Traditionally, the size of the source buffer has been used. That overflowed the destination buffer on occasion... So its better to use a "safer" version of the function: one that specifies both the source and destination buffer sizes.

    You have "safer" functions available via ISO/IEC TR24731. There's a lot more to it, like consistent return values and consistent string handling behavior.

    The "safer" functions are part of the C standard now, so its supposed to be available everywhere. So you should use memcpy_s.

    You can't use it on Linux, because it does not provide the functions (don't believe the marketing hype about standards compliant)). On Linux, you should "roll your own" wrapper.

    Not everyone is a fan of the safer functions. See, for example, Do you use the TR 24731 'safe' functions?. About all I can say about that is: Multiple libunp buffer overflows. Millions of routers and gateways are subject to multiple vulnerable and many remain unpatched. And they were due to bugs that would have been stopped by the safer functions. +1 to everyone who is saying "don't use this Microsoft crap".

    0 讨论(0)
  • 2020-12-09 10:07

    If and when you have an array (real one) you can use the sizeof(array) trick, but note that if you refactor the code and push it somewhere where the array has decayed into a pointer (or if the memory was initially allocated in a pointer (malloc/new) you will need to pass a known size.

    Ignoring the relative sizes of source and destination, that is, assuming that they are the same for the rest of the discussion, if you are using C++ I would recommend a metaprogramming trick that will give you a typesafe size count for arrays and will fail to compile if you try to use it with pointers:

    template <typename T, int N>
    inline int array_memory_size( T (&a)[N] ) { return sizeof a; }
    

    That way:

    int main() {
       int array[10];
       int *ptr = array;
       int orig[10] = { 0 };
       memcpy( array, orig, array_memory_size(array) ); // ok
       //memcpy( ptr, orig, array_memory_size(ptr) ); // compilation error
    }
    

    If at any time you refactor and the code moves to a place where the array has decayed (or you replace an static array for a dynamically allocated one) the compiler will tell you that you need to correct the size calculation.

    0 讨论(0)
  • 2020-12-09 10:09

    It depends. Both arr and pointer are arrays, but sizeof() returns only the correct size for arr, which is declared at compile time.

    int main() {
            int arr[10];
            int * pointer;
            pointer = (int *) malloc(10 * sizeof(int));
            printf("%d\n", sizeof(arr)); // 40
            printf("%d\n", sizeof(pointer)); // 4 or 8
            free(pointer);
    }
    
    0 讨论(0)
  • 2020-12-09 10:10

    Will the second option always work? Regardless of the content?

    The 2nd option works only if you added back the missing ) and dst is a static array (i.e. of type int[123]).

    If dst has unknown size (i.e. int[]), then sizeof dst only returns the pointer size, since dst has been decayed to a pointer. In this case, you need to use sizeof(*dst)*ARRAY_LENGTH.

    0 讨论(0)
  • 2020-12-09 10:11

    If you have allocated using malloc you must state the size of the array

    int * src = malloc(ARRAY_LENGTH*sizeof(*src));
    int * dst1 = malloc(ARRAY_LENGTH*sizeof(*dst));
    memcpy(dst1,src,ARRAY_LENGTH*sizeof(*dst));
    

    If you have allocated with a static array you can just use sizeof

    int dst2[ARRAY_LENGTH];
    memcpy(dst2,src,sizeof(dst2));
    
    0 讨论(0)
提交回复
热议问题