Advertencia PIC 364 relacionada con la inicialización de const

No hay respuestas a esto en Internet que pueda encontrar, y he buscado dos veces en los últimos 4 meses.

En MPLab v8.88 usando Hi-Tech ANSI C Compiler, tengo esta línea de código:

const   uint8 SUM_THRESHOLD_MIN = 15;   /* comment edited out   */

y me sale la advertencia:

Warning [364] C:\*directory edited out* \ *filename_edited_out*.c; 273.35 attempt to modify object qualifed const

(disculpe las ediciones, pero sentí que debería editar detalles personales pero superfluos).

No es mi código, y solo usaría a #define, pero otros quieren usar a const(para aquellos que no saben: el uso de a constgarantiza un encasillado adecuado de un valor, y puede salvarlo de algunos problemas extraños relacionados con el encasillado y tipos de datos; no es mi forma favorita de hacerlo, pero tampoco es una mala idea).

Están constocurriendo varias inicializaciones en el mismo bloque de código, y todas me dan esta advertencia. Están en un archivo .c, en una función nula. Tengo otros archivos con funciones nulas donde inicializo const uint8 y no hay advertencias en esos archivos. Busqué globalmente y no encontré ninguna otra instancia de la variable, excepto donde se usa en la función void (por lo que no hay problemas con la redefinición ni nada por el estilo). Para ser claros, estas constantes no son parte de ninguna estructura ni nada extraño, simplemente se declaran en la función void en el archivo .c.

Tengo uint8 correctamente typedef'd, y no #define'd (ver comentarios).

¿Puede alguien ayudarme a deshacerme de esta advertencia?

EDITAR: si pego uno de los const uint8 en otro archivo .c directamente después de un const uint16 que no arroja el error, así:

const uint16 rate_bias_time_constant[NUM_RATE_CHANNELS][RATE_BIAS_STEP_MAX] = 
    {30,120,480,960,  300,120,180,240,  300,120,180,240 }; // comment edited out
const   uint8 SUM_THRESHOLD_MIN = 15;   /* comment edited out   */

Recibo la advertencia 364 en este archivo para este const uint8 pero no para el const uint16. Si cambio SUM_THRESHOLD_MIN de uint8 a uint16, aún recibo la advertencia. Para completar, si lo cambio de mayúsculas a minúsculas, todavía recibo la advertencia. Si cambio la línea a, por ejemplo:

const uint8 SUM_THRESHOLD_MIN[2] = {15,2};  /* comment edited out   */

No hay advertencia.

¿Es uint8un propio typedefo simplemente un #define?
El código dice: "typedef unsigned char uint8;" y en un archivo diferente hay const int16 y uint8 inicializados de la misma manera sin advertencias.
¿Está ese fragmento de código en un archivo de encabezado (.h) que tal vez se incluye varias veces en un archivo .c?
¿La línea de código está dentro o fuera de una función?
El fragmento de código que arroja la advertencia está en un archivo .c. Todas las declaraciones uint8 (hay 8 advertencias) y una única declaración int16 const en este archivo arrojan esta advertencia, pero hay un const char y un const unsigned int que no arrojan la advertencia en este archivo .c, y hay declaraciones const uint8 en otros archivos que no arrojan advertencias.
@Joe Hass, está en una función nula, y los const uint8 en otros archivos también están en funciones nulas
¿Puede proporcionar alguna información sobre el "bloque de código" donde ocurren estos errores?
Debe proporcionar más información (todo el módulo .c) si desea buenas respuestas.
Por casualidad, ¿los otros archivos tienen directivas de compilación integradas (p. ej., #pragmas) que desactivan esa advertencia en particular?
@m.Alin: Me temo que no puedo hacer público el archivo completo (código de la empresa), pero haré todo lo posible para responder preguntas que ayuden a resolver esto.
@Dave Tweed: No hay #pragma para desactivar las advertencias en los otros archivos. Probablemente soy la primera persona a la que le importa que haya advertencias que compilaron este código. Consideré usar un pragma de supresión de advertencias, pero los otros archivos en este proyecto no me están dando problemas...
@user28910: está en un archivo .c, después de #includes, después de los prototipos locales, en la tercera función del archivo, una función nula, y la constante que causa el problema está en medio de la declaración del resto de los variables locales en esta función nula. La constante int16 que arroja la advertencia está en la misma función, declarada localmente después de un "si". Hay un const unsigned int y un const char que no lanzan las advertencias en este mismo archivo, y otros archivos tienen const uint8 y no lanzan la advertencia.
¿Cómo está construyendo el proyecto? ¿Está compilando archivos desde la línea de comando, usando un Makefile, usando un IDE? ¿Puede hacer una copia de un archivo de trabajo y compilarlo sin advertencias?
@Dave Tweed: estoy usando MPLab IDE v8.88, usando el botón "reconstruir". No entiendo a qué te refieres con hacer una copia de un archivo de trabajo. Tenga en cuenta que edité el compilador C: estoy usando Hi-Tech ANSI C Compiler, no C18.
Tome un archivo que compila sin advertencias y haga una copia con un nombre diferente. ¿Puedes compilarlo sin advertencias? ¿Hay configuraciones por archivo en el propio IDE que podrían estar suprimiendo las advertencias?
@Dave Tweed: no estoy siguiendo a dónde va con la creación de una copia del archivo, y estoy seguro de que es mi propia ignorancia: si hago frente y pego en el proyecto actual y agrego otro archivo, lo haré obtendré errores porque tendré los mismos nombres de función varias veces, y si creo un nuevo proyecto, no puedo compilar porque no tendrá main, etc. ¿Puedo compilar archivos C únicos que no tienen main()? ¿Si es así, cómo?
De acuerdo, intenté pegar una de las líneas que arrojaron el código de advertencia en otro archivo, y también arroja la advertencia allí. Luego intenté analizar esa línea globalmente (fuera de la función) y no hubo ninguna advertencia. Nos estamos acercando, pero aún no hemos llegado...
¿Puedes cortar y pegar toda esta función en uno de los archivos que compila sin advertencias y tiene declaraciones constantes similares y ver si recibes estas advertencias allí?
Sí, agregue una copia del archivo al proyecto e ignore esos otros errores. O cambie el nombre de las funciones en la copia, no importa. El punto es encontrar el conjunto mínimo de diferencias entre dos archivos que marcan la diferencia entre recibir esa advertencia específica o no.
@Bob, ¿podría pasar la función de vacío donde se llama? No necesitamos todo el contenido de la función, pero quizás algunas primeras líneas y algún código que llame a la función.
Lo resolví, ver más abajo. Esperemos que el próximo tipo que tenga este error no se quede con 1 resultado de búsqueda de Google: un sitio web ruso sin información útil... Gracias de nuevo por la ayuda

Respuestas (3)

Lo tengo, y muchas gracias por la ayuda de todos!

Las declaraciones que no arrojan advertencias son matrices o se declaran estáticas const uint8/16. Por alguna razón, el compilador Hi-Tech C está bien con const int/char, const uint8/16 que son arreglos, pero no const uint8/16 a menos que se declare como static const uint8/16.

Debería apreciar que, debido a la extraña arquitectura del PIC16/18, un calificador "const" es una instrucción para colocar esa variable en Flash en lugar de RAM, no una instrucción para decirle al compilador que no se puede cambiar.

Si está tratando de inicializar el valor de una variable automática que es local para una función, entonces ESTÁ tratando de cambiarla en tiempo de ejecución porque intentará escribir ese valor de inicialización en la variable (que se almacena en Flash y es por lo tanto, no se puede escribir (fácilmente) cada vez que se ejecuta la función. La razón por la que funciona cuando la variable se declara estática es porque las variables estáticas que son locales para las funciones solo se inicializan una vez, por lo que no hay inconsistencia lógica de la que el compilador se queje. Supongo que las matrices constantes se tratan de la misma manera.

Esto no explica por qué cuando usa un char o int en lugar de int16/8 o uint16/8 no arroja la misma advertencia, pero tiene el potencial de explicar por qué las const int16/8 de alcance global no estaban dando el error. Es un problema extraño, específico del compilador. ¿Estás seguro de que estos se colocan en flash? Me sigo preguntando sobre eso para el PIC, y una vez lo desarmé, pero nunca estuve al 100%. Pensé que las Pics tenían espacio de código y espacio de memoria, y las instrucciones eran de 14 bits o algo así...
Los PIC16 tienen flash de 14 bits (código de operación de 6 bits, operando de 8 bits); Los PIC18 tienen flash de 16 bits. Ambos almacenan variables constantes en flash; Se puede indicar a algunos compiladores PIC16 que empaquen cadenas de 2x7 bits en cada palabra de 14 bits, lo que puede dificultar la lectura durante la depuración. Ambas familias tienen códigos y espacios de datos completamente separados; lea los capítulos de memoria de cualquier hoja de datos de PIC16/18 para una buena explicación. No puedo explicar el problema "int/char funciona, int8/int16 no", eso no tiene ningún sentido; sin embargo, elige describir un carácter, el compilador debería comportarse exactamente de la misma manera.
Se me ocurrió que la razón por la que las matrices auto const no arrojaban errores es porque un const char[] es en realidad un const char *; el puntero reside en ram y los datos a los que hace referencia residen en flash. El puntero se puede volver a escribir (para que apunte al mismo objeto en flash) cada vez que se ejecuta la función sin causar ningún problema. Además, puede intentar resolver el problema de char-v-uint8 usando #define en lugar de typedef.

Creo que el problema principal es su expectativa de cómo funciona CONST con este compilador en este procesador. Estas cosas no son variables como parece esperar de su descripción. Es muy probable que se implementen como constantes en la memoria del programa, que es esencialmente de solo lectura. Estas cosas no se pueden cambiar en tiempo de ejecución. El error que está recibiendo probablemente esté relacionado con el código de tiempo de ejecución que intenta escribir en CONST, no con la definición de CONST.

Nada de lo cual explica por qué funciona en algunos lugares de su proyecto, pero no en otros.
Sin embargo, no está tratando de cambiar el valor. Tienes permitido inicializar una const; es bastante inútil si no pudieras.
@Dave: Puede ser que solo intente asignar a CONST en tiempo de ejecución en los módulos que fallan.
@usuario: No está nada claro que no esté tratando de cambiar el valor en tiempo de ejecución.
No estamos cambiando el valor en tiempo de ejecución. La advertencia apunta a una línea de código, y esa línea es la declaración de la const.