memcpy_s - memcpy(), ¿cuál debería ser el valor del parámetro de tamaño?
memset (12)
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 una tarea de mantenimiento del hogar actualizar los memcpy ().
Gracias
¿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
.
¿La segunda opción siempre funcionará? ¿Independientemente del contenido?
Solo funcionará si se cumplen ambas condiciones:
-
dst
es una matriz regular, no puntero -
src
ydst
son del mismo tamaño
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, el tamaño del búfer de origen ha sido utilizado. 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 parte del estándar C ahora, por lo que se supone que están disponibles en todas partes. Así que 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 esto 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".
¿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.
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 compilació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);
}
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
simplemente 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*)
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));
Si se asignó dst desde el montón (utilizando malloc, por ejemplo), la segunda solución no funcionará. sizeof (dst) solo funcionará cuando el compilador 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
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 resto de la discusión, si está utilizando C ++, le recomendaría un truco de metaprogramación que le dará un recuento de tamaño seguro para los arreglos y fallará. compila si intentas usarlo con punteros:
template <typename T, int N>
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) ); // compilation 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 compilador le dirá que necesita corregir el cálculo de tamaño.
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.
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);
$> 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 que (sizeof (X) / sizeof (X [0])) sea una constante / variable para no calcular cada vez ... (No sé si los compiladores siempre optimizarán esto)
sizeof(dst)
es correcto solo si dst
es una matriz cuyo tamaño se conoce en tiempo de compilació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.