c++: ¿Por qué al activar un valor de carácter no se alcanza el caso 0xC2?

CorePress2024-01-24  7

Encontré un error en el siguiente código, analiza la cadena C y se supone que detecta caracteres UTF8:

char* pTmp = ...;
...
switch (*pTmp)
{
    case 'o':
    {
        ...     // works fine
        break;
    }   
    case 0xC2:
    {
        ...     // never gets triggered
        break;
    }
}

Sin embargo, el caso 0xC2: nunca se activa.

Mi suposición es que 0xC2 se considera un int y por lo tanto es 194, que es mayor que 127, el valor máximo para el tipo de datos char. Entonces -62 != 194

O puede haber algún desbordamiento o una promoción de números enteros aquí.

Escribir el interruptor ((unsigned char)*pTmp) soluciona el problema.

Pero me gustaría aclarar qué está pasando realmente aquí y qué reglas se aplican.

También estoy abierto a cambiar el título, pero no se me ocurrió nada mejor.

caso 0xC2: se compara con un valor int decimal 196 pero si char tiene signo entonces es como usted dice, -62. Puede verificar que 0xC2 sea de tipo int con printf("%zu\n", sizeof(0xC2));. Aparte: tenga en cuenta que 'o' también es un valor int.

Veleta

27/03/2021 a las 21:04

Copiando y pegando un comentario aquí: "C89 6.1.2.5 "Hay tres tipos de caracteres, designados como char , firmado char y char sin firmar. C11 6.2.5p15 "Los tres tipos char, char firmado y char sin firmar se denominan colectivamente tipos de caracteres". 6.2.5fn45 "char es un tipo independiente de los otros dos y no es compatible con ninguno""

- Karl Knechtel

27/03/2021 a las 21:17

Intenté darle un título mejor según cómo formulaste la pregunta.

- Karl Knechtel

27/03/2021 a las 21:24

Podrías usar una constante de carácter, '\xc2', para que tenga un valor de carácter.

- Eric Postpischil

27/03/2021 a las 21:36



------------------------------------

Entiendo esto al agregar -Wall aquí

warning: case label value exceeds maximum value for type [-Wswitch-outside-range]
   14 |             case 0xC2:

Entonces sí, tu razonamiento es correcto.

1

Esta es información relevante, pero el resultado es específico de la implementación.

- Karl Knechtel

27/03/2021 a las 21:21



------------------------------------

¿Está firmado el carácter char?

Es específico de la implementación si char tiene el mismo rango que char firmado o no firmado. En el caso de OP, char tiene el rango [-128 ... 127], por lo que el caso 0xC2: nunca coincide.

Pero me gustaría aclarar qué está pasando realmente aquí y qué reglas se aplican.

Las funciones de cadena de la biblioteca estándar de C tienen muchos parámetros que son char *, pero esas funciones de la biblioteca actúan internamente como si apuntaran a unsdatos de caracteres firmados

Para todas las funciones en esta subcláusula, cada carácter se interpretará como si tuviera el tipo char unsigned (y por lo tanto cada representación de objeto posible es válida y tiene un valor diferente). C17dr § 7.24.1 3

Para que coincida con eso, el código de OP debería hacer lo mismo. Hacerlo también permitirá que *upTmp coincida potencialmente con 0xC2.

char* pTmp = ...;
unsigned char* upTmp = ( unsigned char*) pTmp;

switch (*upTmp)

   case 0xC2:

Como alternativa al uso de la constante hexadecimal 0xC2, utilice una constante de caracteres: '\xC2' para que coincida con el rango de caracteres. @Eric Postpischil.

[Pedante]

"El interruptor ((unsigned char)*pTmp) soluciona el problema". - está lo suficientemente cerca.

Esta "solución" funciona con caracteres firmados en complemento a 2, así como cuando el carácter definido por la implementación coincide con un carácter sin firmar.

Para los casos restantes, casi inexistentes, en los queEl carácter está firmado y no es complemento a 2, la solución es incorrecta ya que se debe acceder a los caracteres a través de un carácter sin firmar *; de lo contrario, se usa el valor incorrecto.

el interruptor (*(unsigned char *)pTmp) funciona correctamente en todos los casos.

1

2

Si, por cualquier motivo, utilizan char en lugar de unsigned char, pueden usar una constante de carácter, como en el caso '\xC2': para obtener el valor de char correspondiente. Y usar una constante de carácter en lugar de una constante entera expresa mejor que están activando un carácter.valor del carácter.

- Eric Postpischil

27/03/2021 a las 21:41

Su guía para un futuro mejor - libreflare
Su guía para un futuro mejor - libreflare