memcpy (), ¿cuál debería ser el valor del parámetro de tamaño?

Quiero copiar una matriz int a otra matriz int. Usan la misma definición para la longitud, por lo que siempre serán de la misma longitud.

¿Cuáles son las ventajas y desventajas de las siguientes dos alternativas del parámetro size para memcpy ()?

memcpy(dst, src, ARRAY_LENGTH*sizeof(int)); 

o

 memcpy(dst, src, sizeof(dst)); 

¿La segunda opción siempre funcionará? ¿Independientemente del contenido?

Una cosa que favorece a la última es que si se cambiara la matriz, sería un mantenimiento de la casa actualizar los memcpy ().

Gracias

Mientras dst se declare como una matriz con un tamaño, sizeof devolverá el tamaño de esa matriz en bytes:

 int dst[ARRAY_LENGTH]; memcpy( dst, src, sizeof(dst) ); // Good, sizeof(dst) returns sizeof(int) * ARRAY_LENGTH 

Si dst resulta ser un puntero al primer elemento de dicha matriz (que es del mismo tipo que la propia matriz), no funcionará:

 int buffer[ARRAY_LENGTH]; int* dst = &buffer[0]; memcpy( dst, src, sizeof(dst) ); // Bad, sizeof(dst) returns sizeof(int*) 

sizeof(dst) es correcto solo si dst es una matriz cuyo tamaño se conoce en tiempo de comstackción: como int arr[ARRAY_LENGTH] o una matriz de longitud variable C99; de lo contrario, devuelve el tamaño de un puntero, no la longitud de la matriz de destino.

Para evitar errores futuros, sea coherente y prefiera la primera forma: tamaño de tipo * longitud.

Si y cuando tiene una matriz (real) puede usar el truco sizeof(array) , pero tenga en cuenta que si refactoriza el código y lo empuja en algún lugar donde la matriz se haya convertido en un puntero (o si la memoria se asignó inicialmente en un puntero (malloc / nuevo) deberá pasar un tamaño conocido.

Ignorar los tamaños relativos de origen y destino, es decir, suponiendo que sean los mismos para el rest de la discusión, si está utilizando C ++, le recomendaría un truco de metaprogtwigción que le dará un recuento de tamaño seguro para las matrices y no podrá comstack si intentas usarlo con punteros:

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

De esa manera:

 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) ); // comstacktion error } 

Si en cualquier momento refactoriza y el código se mueve a un lugar donde la matriz ha decaído (o si reemplaza una matriz estática por una asignada dinámicamente), el comstackdor le dirá que necesita corregir el cálculo de tamaño.

¿La segunda opción siempre funcionará? ¿Independientemente del contenido?

La segunda opción solo funciona si se agregaron nuevamente las que faltan ) y dst es una matriz estática (es decir, de tipo int[123] ).

Si dst tiene un tamaño desconocido (es decir, int[] ), sizeof dst solo devuelve el tamaño del puntero, ya que dst ha reducido a un puntero. En este caso, debe usar sizeof(*dst)*ARRAY_LENGTH .

Si ha asignado utilizando malloc debe indicar el tamaño de la matriz

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

Si ha asignado una matriz estática, puede usar sizeof

 int dst2[ARRAY_LENGTH]; memcpy(dst2,src,sizeof(dst2)); 

Suponiendo que dst es del tipo int *, sizeof (dst) devolverá el tamaño del propio puntero (es decir, 4 en un sistema de 32 bits, 8 en un sistema de 64 bits), por lo que su segundo ejemplo solo copiará este número de bytes, mientras que el primero utilizará correctamente el tamaño real del contenido.

¿La segunda opción siempre funcionará? ¿Independientemente del contenido?

Solo funcionará si se cumplen ambas condiciones:

  • dst es una matriz regular, no puntero
  • src y dst son del mismo tamaño

sizeof (X) siempre te da el NÚMERO DE BYTES de “X” si X es una matriz uint16_t de 10, entonces sizeof (X) devolverá 20

 uint16_t X[10]={0}; cout<<"sizeof x: "< sizeof x: 20 

Si desea la cantidad de elementos que tiene que hacer un poco de aritmética de bytes:
8 bits = 1 byte
16 bits = 2 bytes
32 bits = 4 bytes
64 bits = 8 bytes

para obtener la cantidad de elementos que podrías hacer:

  numb_of_elements = ( sizeof(X)/sizeof(X[0]) ); 

Resultando en:

 uint32_t source[100]={0}; memcpy((void*) dest, (void*) source, ( sizeof(source)/sizeof(source[0]) )); 

por supuesto, probablemente querrá hacer de (sizeof (X) / sizeof (X [0])) una constante / variable para no calcular cada vez … (No sé si los comstackdores siempre optimizarán esto)

Depende. Tanto arr como pointer son matrices, pero sizeof () solo devuelve el tamaño correcto para arr, que se declara en el momento de la comstackción.

 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); } 

Si se asignó dst desde el montón (utilizando malloc, por ejemplo), la segunda solución no funcionará. sizeof (dst) solo funcionará cuando el comstackdor lo sepa. Por ejemplo, el siguiente ejemplo fallará ya que sizeof (dst) será igual al tamaño de un puntero (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 

Este segmento de código funcionará siempre:

 #define ARRAY_LENGTH 10 int *dst; dst = malloc(ARRAY_LENGTH*sizeof(int)); memcpy(dst, src, ARRAY_LENGTH*sizeof(int)); // sizeof would be 40 bytes 

¿Qué tal si?

 memcpy(dst, src, &src[ARRAY_LENGTH] - &src[0]); 

Esto debería funcionar incluso si el tamaño de los elementos individuales fuera más pequeño que el tamaño tomado por cada elemento en la matriz real.

memcpy (), ¿cuál debería ser el valor del parámetro de tamaño?

Debe ser el mínimo entre el tamaño del búfer de origen y el tamaño del búfer de destino.

Tradicionalmente, se ha utilizado el tamaño del búfer de origen. Eso desbordó el búfer de destino en ocasiones … Por lo tanto, es mejor usar una versión “más segura” de la función: una que especifique los tamaños del búfer de origen y de destino.

Tiene funciones “más seguras” disponibles a través de ISO / IEC TR24731 . Hay mucho más que hacer, como valores de retorno consistentes y un comportamiento de manejo de cadenas consistente.

Las funciones “más seguras” son ahora parte del estándar C, por lo que se supone que están disponibles en todas partes. Entonces deberías usar memcpy_s .

No puede usarlo en Linux, ya que no proporciona las funciones (no crea que la exageración de marketing sobre el cumplimiento de estándares). En Linux, debe “enrollar su propio” envoltorio.

No todos son fanáticos de las funciones más seguras. Vea, por ejemplo, ¿Utiliza las funciones ‘seguras’ de TR 24731? . Sobre todo lo que puedo decir sobre eso es: múltiples desbordamientos de búfer de libunp . Millones de enrutadores y puertas de enlace están sujetos a múltiples vulnerabilidades y muchos permanecen sin parchear. Y se debieron a errores que habrían sido detenidos por las funciones más seguras. +1 a todos los que están diciendo “no uses esta mierda de Microsoft”.