utiliza que para array c language-lawyer strict-aliasing

que - ¿Cuál es el tipo efectivo de un objeto escrito por memset?



memset linux (1)

Código 1:

unsigned int *p = malloc(sizeof *p); memset(p, 0x55, sizeof *p); unsigned int u = *p;

Código 2:

void *d = malloc(50); *(double *)d = 1.23; memset(d, 0x55, 50); unsigned int u = *(unsigned int *)d;

En cada caso, ¿qué efecto tiene memset sobre el tipo efectivo del objeto en el espacio malloc''d; ¿Y entonces es inicializar u correcto o una violación de alias estricta?

La definición de tipo efectivo (C11 6.5 / 6) es:

El tipo efectivo de un objeto para un acceso a su valor almacenado es el tipo declarado del objeto, en su caso. Si un valor se almacena en un objeto que no tiene un tipo declarado a través de un lvalue que tiene un tipo que no es un tipo de carácter, entonces el tipo de lvalue se convierte en el tipo efectivo del objeto para ese acceso y para los accesos posteriores que no modifican el valor. valor almacenado. Si un valor se copia en un objeto que no tiene un tipo declarado utilizando memcpy o memmove , o se copia como una matriz de tipo de carácter, entonces el tipo efectivo del objeto modificado para ese acceso y para los accesos posteriores que no modifiquen el valor es el tipo efectivo del objeto desde el cual se copia el valor, si tiene uno. Para todos los demás accesos a un objeto que no tiene un tipo declarado, el tipo efectivo del objeto es simplemente el tipo del valor de l utilizado para el acceso.

Sin embargo, no está claro si memset comporta como la escritura a través de un valor de tipo de carácter, o algo más. La descripción de memset (7.24.6.1) no es muy iluminadora:

La función memset copia el valor de c (convertido en un unsigned char ) en cada uno de los primeros n caracteres del objeto apuntado por s.


Mi 50ct:

Primero, rompo esto en oraciones para una referencia más fácil:

  1. El tipo efectivo de un objeto para un acceso a su valor almacenado es el tipo declarado del objeto, en su caso.
  2. Si un valor se almacena en un objeto que no tiene un tipo declarado a través de un lvalue que tiene un tipo que no es un tipo de carácter, entonces el tipo de lvalue se convierte en el tipo efectivo del objeto para ese acceso y para los accesos posteriores que no modifican el valor. valor almacenado.
  3. Si un valor se copia en un objeto que no tiene un tipo declarado utilizando memcpy o memmove, o se copia como una matriz de tipo de carácter, entonces el tipo efectivo del objeto modificado para ese acceso y para los accesos posteriores que no modifiquen el valor es el tipo efectivo del objeto desde el cual se copia el valor, si tiene uno.
  4. Para todos los demás accesos a un objeto que no tiene un tipo declarado, el tipo efectivo del objeto es simplemente el tipo del valor de l utilizado para el acceso.

La nota al pie podría ayudar aquí: "87) Los objetos asignados no tienen un tipo declarado". .

ADN: "no se aplica"

Caso 1:

  • memset(...) : 1: ADN (sin tipo declarado), 2: ADN (memset se escribe a char - semántica), 3: ADN (ni memcpy ni memmove), 4: char [] para memset solo internamente (no permanente ).
  • unsigned int u = *p : 1: DNA (tipo no declarado), 2/3: DNA (no write, pero read), 4: type of lvalue is unsigned int .

Conclusión: no hay violación, pero la interpretación está definida por la implementación, ya que el valor real depende de la alineación dentro de la variable y la endianess.

Caso 2:

  • *(double *)d = 1.23; : 2: d convierte en double * para esto y las siguientes lecturas.
  • memset(d, 0x55, 50); : igual que para el caso 1.
  • unsigned int u = *(unsigned int *)d : d sigue siendo double * : bang!

De cualquier manera, memset() es de uso memset() no char , excepto si se usa 0 , que aún depende de la implementación , ya que ni (float)0.0 , ni el puntero nulo deben ser en realidad "todos los bits cero".

Finalmente:

  • La oración 2 no se aplica a memset , ya que internamente, memset() copia por char: "... of c (se convierte en un char sin signo) en cada uno de los primeros n caracteres ..." (o utiliza la semántica de char , al menos ; la implementación real es irrelevante aquí).
  • La oración 3 tampoco se aplica a memset() , ya que solo se aplica a memcpy / memmove o cuando se copia como "una matriz de tipo de carácter". Lo que tampoco lo hace (pero el primero sí lo hace, por lo que la condición or simplemente hace un bucle de copia explícito equivalente a las funciones).
  • memset() no cambia el tipo efectivo del objeto. Eso difiere de memcpy y memmove . Eso resulta de la oración 4, que no incluye "... para ese acceso y para accesos subsiguientes ..." como 2 y 3 estado y 1 implica.

Espero que ayude. La crítica constructiva es bienvenida.