varias tipos tipografico tipo publicidad para mac llamativas letras letra instalar fuentes descargar como color catalogo cambiar azules c strict-aliasing type-punning

tipos - letras llamativas para publicidad



La corrección de la desreferenciación del puntero con tipo de letra romperá el alias estricto (5)

Emitir puntero a unsigned y luego volver a apuntar.

unsigned int Tamaño_recibido = ntohl (* ((sin signo *) ((sin signo) dcc-> incoming_buf)));

Estoy tratando de corregir dos advertencias al compilar un programa específico utilizando GCC. Las advertencias son:

advertencia: la desreferenciación del puntero con tipo de letra infringirá las reglas de alias estricto [-Wstrict-aliasing]

y los dos culpables son:

unsigned int received_size = ntohl (*((unsigned int*)dcc->incoming_buf));

y

*((unsigned int*)dcc->outgoing_buf) = htonl (dcc->file_confirm_offset);

entrante_buf y saliente_buf se definen de la siguiente manera:

char incoming_buf[LIBIRC_DCC_BUFFER_SIZE]; char outgoing_buf[LIBIRC_DCC_BUFFER_SIZE];

Esto parece sutilmente diferente a los otros ejemplos de esa advertencia que he estado examinando. Preferiría solucionar el problema en lugar de deshabilitar las comprobaciones de alias estricto.

Ha habido muchas sugerencias para utilizar un sindicato: ¿cuál podría ser un sindicato adecuado para este caso?


En primer lugar, examinemos por qué obtiene las advertencias de violación de alias.

Las reglas de alias simplemente dicen que solo se puede acceder a un objeto a través de su propio tipo, su variante con signo / sin signo, o mediante un tipo de carácter ( char , signed char , unsigned char ).

C dice que violar las reglas de alias invoca un comportamiento indefinido (¡ así que no! ).

En esta línea de su programa:

unsigned int received_size = ntohl (*((unsigned int*)dcc->incoming_buf));

Aunque los elementos de la matriz incoming_buf son de tipo char , los está accediendo como unsigned int . De hecho, el resultado del operador de desreferencia en la expresión *((unsigned int*)dcc->incoming_buf) es de tipo unsigned int .

Esto es una violación de las reglas de aliasing, ya que solo tiene derecho a acceder a los elementos de la matriz incoming_buf través de (ver resumen de reglas más arriba) char , signed char o unsigned char .

Tenga en cuenta que tiene exactamente el mismo problema de alias en su segundo culpable:

*((unsigned int*)dcc->outgoing_buf) = htonl (dcc->file_confirm_offset);

char elementos char de outgoing_buf través de unsigned int , por lo que es una violación de aliasing.

Solución propuesta

Para solucionar su problema, puede intentar que los elementos de sus arreglos se definan directamente en el tipo al que desea acceder:

unsigned int incoming_buf[LIBIRC_DCC_BUFFER_SIZE / sizeof (unsigned int)]; unsigned int outgoing_buf[LIBIRC_DCC_BUFFER_SIZE / sizeof (unsigned int)];

(Por cierto, el ancho del unsigned int está definido por la implementación, por lo que debería considerar el uso de uint32_t si su programa asume que el unsigned int es de 32 bits).

De esta manera, podría almacenar objetos unsigned int en su matriz sin violar las reglas de alias accediendo al elemento a través del tipo char , de esta manera:

*((char *) outgoing_buf) = expr_of_type_char;

o

char_lvalue = *((char *) incoming_buf);

EDITAR:

He revisado completamente mi respuesta, en particular, explico por qué el programa recibe las advertencias de alias del compilador.


Para solucionar el problema, no juegues y alias ! La única forma "correcta" de leer un tipo T es asignar un tipo T y completar su representación si es necesario:

uint32_t n; memcpy(&n, dcc->incoming_buf, 4);

En resumen: si desea un entero, necesita hacer un entero. No hay forma de evitarlo de una manera condonada por el lenguaje.

La única conversión de puntero que está permitida (para propósitos de E / S, generalmente) es tratar la dirección de una variable existente de tipo T como un char* , o más bien, como el puntero al primer elemento de una matriz de caracteres. de tamaño sizeof(T) .


Si puedo, IMHO, para este caso, el problema es el diseño de las API de ntohl y htonl y de funciones relacionadas. No deberían haberse escrito como argumento numérico con retorno numérico. (y sí, entiendo el punto de optimización de macros) Deberían haber sido diseñados como el lado ''n'' como un puntero a un búfer. Cuando esto se hace, todo el problema desaparece y la rutina es precisa, independientemente de cuál sea el servidor. Por ejemplo (sin intentar optimizar):

inline void safe_htonl(unsigned char *netside, unsigned long value) { netside[3] = value & 0xFF; netside[2] = (value >> 8) & 0xFF; netside[1] = (value >> 16) & 0xFF; netside[0] = (value >> 24) & 0xFF; };


union { const unsigned int * int_val_p; const char* buf; } xyz; xyz.buf = dcc->incoming_buf; unsigned int received_size = ntohl(*(xyz.int_val_p));

Explicación simplificada 1. El estándar de c ++ indica que debe intentar alinear los datos usted mismo, g ++ hace un esfuerzo adicional para generar advertencias sobre el tema. 2. solo debe intentarlo si comprende completamente la alineación de datos en su arquitectura / sistema y dentro de su código (por ejemplo, el código anterior es algo seguro en Intel 32/64; alineación 1; Win / Linux / Bsd / Mac) 3. La única razón práctica para usar el código anterior es evitar las advertencias del compilador, CUÁNDO y SI, si sabe lo que está haciendo