c++ - que - ¿Por qué memset() inicializa incorrectamente int?
memset char c (9)
¿Por qué la salida del siguiente programa es 84215045
?
int grid[110];
int main()
{
memset(grid, 5, 100 * sizeof(int));
printf("%d", grid[0]);
return 0;
}
Bueno, el memset
escribe bytes, con el valor seleccionado. Por lo tanto, un int se verá más o menos así:
00000101 00000101 00000101 00000101
Que luego se interpreta como 84215045.
Como memset escribe bytes, generalmente lo utilizo para establecer una matriz int a cero como:
int a[100];
memset(a,0,sizeof(a));
o puede usarlo para establecer una matriz de caracteres, ya que un carácter es exactamente un byte:
char a[100];
memset(a,''*'',sizeof(a));
Además, una matriz int también puede establecerse en -1 por memset:
memset(a,-1,sizeof(a));
Esto es porque -1 es 0xffffffff en int, y es 0xff en char (un byte).
En realidad, no ha dicho lo que quiere que haga su programa.
Suponiendo que desea establecer cada uno de los primeros 100 elementos de la grid
en 5 (e ignorando la discrepancia entre 100
y 110
), solo haga esto:
for (int i = 0; i < 100; i ++) {
grid[i] = 5;
}
Entiendo que le preocupa la velocidad, pero su preocupación probablemente esté fuera de lugar. Por un lado, memset()
probablemente se optimice y, por lo tanto, sea más rápido que un simple bucle. Por otro lado, la optimización probablemente consistirá en escribir más de un byte a la vez, que es lo que hace este ciclo. Por otro lado, memset()
es un bucle de todos modos; escribir el ciclo explícitamente en lugar de enterrarlo en una llamada de función no cambia eso. Por otro lado, incluso si el ciclo es lento, no es probable que importe; concéntrese en escribir código claro y piense en optimizarlo si las mediciones reales indican que hay un problema de rendimiento significativo.
Ha pasado muchos órdenes de magnitud más tiempo escribiendo la pregunta de lo que su computadora pasará configurando la grid
.
Finalmente, antes de que me quede sin manos (¡demasiado tarde!), No importa qué tan rápido memset()
sea si no hace lo que desea. (¡No establecer la grid
es aún más rápido!)
Este código ha sido probado. Aquí hay una manera de configurar una matriz "entera" a un valor entre 0 y 255.
MinColCost=new unsigned char[(Len+1) * sizeof(int)];
memset(MinColCost,0x5,(Len+1)*sizeof(int));
memset(MinColCost,0xff,(Len+1)*sizeof(int));
Si man memset
en tu caparazón, te dice que
void * memset(void *b, int c, size_t len)
Una simple explicación en inglés de esto sería que llena una cadena byte b
de longitud len
con cada byte un valor c
.
Para tu caso,
memset(grid, 5, 100 * sizeof(int));
Desde sizeof(int)==4
, así las piezas de código anteriores se veían así:
for (int i=0; i<100; i++)
grid[i]=0x05050505;
O
char *grid2 = (char*)grid;
for (int i=0; i<100*sizeof(int); i++)
grid2[i]=0x05;
Se imprimiría 84215045
Pero en la mayoría de los códigos C, queremos inicializar una pieza de bloque de memoria con valor cero.
- tipo de
char
->/0
oNUL
-
int
tipo ->0
- tipo de
float
->0.0f
- tipo
double
->0.0
- tipo de puntero ->
nullptr
Y ya sea gcc o clang, etc., los compiladores modernos pueden encargarse de esto automáticamente.
// variadic length array (VLA) introduced in C99
int len = 20;
char carr[len];
int iarr[len];
float farr[len];
double darr[len];
memset(carr, 0, sizeof(char)*len);
memset(iarr, 0, sizeof(int)*len);
memset(farr, 0, sizeof(float)*len);
memset(darr, 0, sizeof(double)*len);
for (int i=0; i<len; i++)
{
printf("%2d: %c/n", i, carr[i]);
printf("%2d: %i/n", i, iarr[i]);
printf("%2d: %f/n", i, farr[i]);
printf("%2d: %lf/n", i, darr[i]);
}
Pero tenga en cuenta que el Comité C ISO no impone tales definiciones, es específico del compilador.
memset
establece cada byte del búfer de destino en el valor especificado. En su sistema, un int
es cuatro bytes, cada uno de los cuales es 5 después de la llamada a memset
. Por lo tanto, la grid[0]
tiene el valor 0x05050505
(hexadecimal), que es 84215045
en decimal.
Algunas plataformas proporcionan API alternativas a memset
que escriben patrones más amplios en el búfer de destino; por ejemplo, en OS X o iOS, puede usar:
int pattern = 5;
memset_pattern4(grid, &pattern, sizeof grid);
para obtener el comportamiento que pareces esperar ¿A qué plataforma estás apuntando?
En C ++, solo debe usar std::fill_n
:
std::fill_n(grid, 100, 5);
memset
trata de establecer bytes, no valores. Una de las muchas maneras de establecer valores de matriz en C ++ es std::fill_n
:
std::fill_n(grid, 100, 5);
No use memset.
Establece cada byte []
de la memoria en el valor de 5. Cada int tiene 4 bytes de longitud [5][5][5][5]
, que el compilador interpreta correctamente como 5 * 256 * 256 * 256 + 5 * 256 * 256 + 5 * 256 + 5 = 84215045. En su lugar, use un bucle for, que tampoco requiere sizeof (). En general, sizeof () significa que estás haciendo algo de la manera difícil.
for(int i=0; i<110; ++i)
grid[i] = 5;
memset(grid, 5, 100 * sizeof(int));
Está configurando 400 bytes, comenzando en la (char*)grid
y terminando en (char*)grid + (100 * sizeof(int))
, hasta el valor 5
(los moldes son necesarios aquí porque memset
trata en bytes , mientras que la aritmética del puntero ofertas en objects
.
84215045
en hex es 0x05050505
; dado que int
(en su plataforma / compilador / etc.) está representado por cuatro bytes, cuando lo imprime, obtiene "cuatro cincos".