PIC-Warnung 364 im Zusammenhang mit der Initialisierung von const

Es gibt keine Antworten darauf im Internet, die ich finden konnte, und ich habe in den letzten 4 Monaten zweimal nachgesehen.

In MPLab v8.88 mit dem Hi-Tech ANSI C Compiler habe ich diese Codezeile:

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

und ich bekomme die Warnung:

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

(Entschuldigen Sie die Änderungen, aber ich hatte das Gefühl, ich sollte persönliche, aber überflüssige Details herausschneiden).

Es ist nicht mein Code, und ich würde einfach ein verwenden #define, aber andere möchten ein verwenden const(für diejenigen, die es nicht wissen: Die Verwendung von constgarantiert eine korrekte Typumwandlung eines Werts und kann Sie vor einigen seltsamen Problemen im Zusammenhang mit der Typumwandlung bewahren und Datentypen; es ist nicht meine Lieblingsmethode, aber es ist auch keine schlechte Idee).

Es finden mehrere constInitialisierungen im selben Codeblock statt, und alle geben mir diese Warnung. Sie befinden sich in einer .c-Datei in einer void-Funktion. Ich habe andere Dateien mit void-Funktionen, in denen ich const uint8 initialisiere, und es gibt keine Warnungen in diesen Dateien. Ich habe global gesucht und keine andere Instanz der Variablen gefunden, außer dort, wo sie in der void-Funktion verwendet wird (es gibt also keine Probleme mit der Neudefinition oder ähnlichem). Um es klar zu sagen, diese Konstanten sind nicht Teil einer Struktur oder etwas Seltsamem, sie werden nur in der void-Funktion in der .c-Datei deklariert.

Ich habe uint8 richtig typedef'd und nicht #define'd (siehe Kommentare).

Kann mir jemand helfen, diese Warnung loszuwerden?

BEARBEITEN: Wenn ich einen der const uint8 in eine andere .c-Datei direkt nach einem const uint16 einfüge, der den Fehler nicht auslöst, wie folgt:

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   */

Ich erhalte die Warnung 364 in dieser Datei für diese Konstante uint8, aber nicht für die Konstante uint16. Wenn ich SUM_THRESHOLD_MIN von uint8 in uint16 ändere, erhalte ich immer noch die Warnung. Der Vollständigkeit halber, wenn ich es von Großbuchstaben in Kleinbuchstaben ändere, erhalte ich immer noch die Warnung. Ändere ich die Zeile z.

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

Es gibt keine Warnung.

Ist uint8ein richtiges typedefoder nur ein #define?
Der Code sagt: "typedef unsigned char uint8;" und in einer anderen Datei gibt es const int16 und uint8, die auf die gleiche Weise ohne Warnungen initialisiert werden.
Befindet sich dieser Codeabschnitt in einer Header-Datei (.h), die möglicherweise mehrmals in einer .c-Datei enthalten ist?
Ist die Codezeile innerhalb einer Funktion oder außerhalb einer Funktion?
Der Codeabschnitt, der die Warnung auslöst, befindet sich in einer .c-Datei. Alle uint8 (es gibt 8 Warnungen) und eine einzelne int16 const-Deklaration in dieser Datei lösen diese Warnung aus, aber es gibt ein const char und ein const unsigned int, die die Warnung nicht in dieser .c-Datei auslösen, und es gibt sie const uint8-Deklarationen in anderen Dateien, die keine Warnungen auslösen.
@Joe Hass, es ist eine void-Funktion, und die const uint8 in anderen Dateien sind auch in void-Funktionen
Können Sie einige Informationen zu dem "Codeblock" bereitstellen, in dem diese Fehler auftreten?
Sie sollten weitere Informationen (das gesamte .c-Modul) bereitstellen, wenn Sie gute Antworten wünschen.
Haben die anderen Dateien zufällig Compiler-Direktiven (z. B. #pragmas) eingebettet, die diese spezielle Warnung ausschalten?
@m.Alin: Ich fürchte, ich kann nicht die gesamte Datei für die Öffentlichkeit freigeben (Firmencode), aber ich werde mein Bestes geben, um Fragen zu beantworten, die dabei helfen, dies herauszufinden.
@Dave Tweed: Es gibt keine #pragmas zum Abschalten von Warnungen in den anderen Dateien. Ich bin wahrscheinlich die erste Person, die sich überhaupt darum kümmert, dass es Warnungen gibt, die diesen Code kompiliert haben. Ich habe überlegt, ein Pragma zum Unterdrücken von Warnungen zu verwenden, aber die anderen Dateien in diesem Projekt bereiten mir keine Probleme ...
@ user28910: Es ist in einer .c-Datei, nach #includes, nach den lokalen Prototypen, in der dritten Funktion der Datei, eine void-Funktion, und die Konstante, die die Probleme verursacht, befindet sich mitten in der Deklaration des Rests der lokale Variablen in dieser void-Funktion. Die int16-Konstante, die die Warnung auslöst, befindet sich in derselben Funktion und wird lokal nach einem „if“ deklariert. Es gibt ein const unsigned int und ein const char, die die Warnungen in derselben Datei nicht ausgeben, und andere Dateien haben const uint8 und geben die Warnung nicht aus.
Wie erstellen Sie das Projekt – kompilieren Sie Dateien von der Befehlszeile aus, mit einem Makefile, mit einer IDE? Können Sie eine Kopie einer Arbeitsdatei erstellen und diese ohne Warnungen kompilieren?
@Dave Tweed: Ich verwende die MPLab IDE v8.88 und verwende die Schaltfläche "Neu erstellen". Ich verstehe nicht, was Sie damit meinen, eine Kopie einer Arbeitsdatei zu erstellen. Beachten Sie, dass ich den C-Compiler bearbeitet habe: Ich verwende den Hi-Tech ANSI C Compiler, nicht C18.
Nehmen Sie eine Datei, die ohne Warnungen kompiliert wird, und erstellen Sie eine Kopie davon mit einem anderen Namen. Können Sie es ohne Warnungen kompilieren? Gibt es Einstellungen pro Datei in der IDE selbst, die möglicherweise Warnungen unterdrücken?
@Dave Tweed: Ich verfolge nicht, wohin Sie mit dem Erstellen einer Kopie der Datei gehen, und ich bin mir sicher, dass es meine eigene Unwissenheit ist: Wenn ich das aktuelle Projekt bearbeite und einfüge und eine weitere Datei hinzufüge, werde ich es tun bekomme Fehlermeldungen, weil ich mehrmals die gleichen Funktionsnamen habe, und wenn ich ein neues Projekt erstelle, kann ich nicht bauen, weil es kein main hat usw. Kann ich einzelne C-Dateien kompilieren, denen main() fehlt? Wenn das so ist, wie?
Okay, ich habe versucht, eine der Zeilen einzufügen, die den Warncode in eine andere Datei geworfen haben, und die Warnung wird auch dort ausgegeben. Dann habe ich versucht, diese Zeile global (außerhalb der Funktion) zu definieren, und es gab keine Warnung. Wir kommen näher, aber wir sind noch nicht da...
Können Sie diese gesamte Funktion ausschneiden und in eine der Dateien einfügen, die ohne Warnungen kompiliert wird und ähnliche const-Deklarationen hat, und sehen, ob Sie diese Warnungen dort erhalten?
Ja, fügen Sie dem Projekt eine Kopie der Datei hinzu und ignorieren Sie diese anderen Fehler. Oder benennen Sie die Funktionen in der Kopie um, es spielt keine Rolle. Es geht darum, die Mindestmenge an Unterschieden zwischen zwei Dateien zu finden, die den Unterschied zwischen dem Erhalt dieser bestimmten Warnung ausmachen oder nicht.
@Bob könntest du an der void-Funktion vorbeikommen, wo sie aufgerufen wird? Wir brauchen nicht den gesamten Funktionsinhalt, aber vielleicht ein paar erste Zeilen und etwas Code, der die Funktion aufruft
Ich habe es gelöst, siehe unten. Hoffentlich wird der nächste Typ, der diesen Fehler hat, nicht mit 1 Google-Suchergebnis zurückgelassen: eine russische Website ohne nützliche Informationen ... Nochmals vielen Dank für die Hilfe

Antworten (3)

Ich habe es verstanden und vielen Dank für die Hilfe aller!

Die Deklarationen, die keine Warnungen auslösen, sind entweder Arrays oder sie werden als statische const uint8/16 deklariert. Aus irgendeinem Grund ist der Hi-Tech-C-Compiler in Ordnung mit const int/char, const uint8/16, die Arrays sind, aber nicht mit const uint8/16, es sei denn, sie werden als statische const uint8/16 deklariert.

Sie sollten wissen, dass aufgrund der ungewöhnlichen Architektur des PIC16/18 ein „const“-Qualifizierer eine Anweisung ist, diese Variable im Flash statt im RAM zu platzieren, und keine Anweisung, dem Compiler mitzuteilen, dass sie nicht geändert werden darf.

Wenn Sie versuchen, den Wert einer Auto-Variablen zu initialisieren, die lokal für eine Funktion ist, versuchen Sie, ihn zur Laufzeit zu ändern, da versucht wird, diesen Initialisierungswert in die Variable zu schreiben (die in Flash gespeichert ist und ist daher nicht (einfach) beschreibbar) jedes Mal, wenn die Funktion ausgeführt wird. Der Grund, warum es funktioniert, wenn die Variable als statisch deklariert wird, liegt darin, dass statische Variablen, die lokal für Funktionen sind, immer nur einmal initialisiert werden, sodass es keine logische Inkonsistenz gibt, über die der Compiler jammern könnte. Meine Vermutung ist, dass die konstanten Arrays auf die gleiche Weise behandelt werden.

Dies erklärt nicht, warum, wenn Sie ein char oder int im Gegensatz zu int16/8 oder uint16/8 verwenden, es nicht die gleiche Warnung auslöst, aber es hat das Potenzial zu erklären, warum konstante int16/8 mit globalem Bereich nicht gaben der Fehler. Es ist ein seltsames, Compiler-spezifisches Problem. Sind Sie sicher, dass diese im Flash platziert sind? Ich wundere mich immer wieder darüber für den PIC und habe einmal eine Demontage durchlaufen, war aber nie zu 100% dabei. Ich dachte, die Bilder hätten Code- und Speicherplatz, und die Anweisungen wären 14 Bit lang oder so etwas Seltsames ...
PIC16s haben 14-Bit-Flash (6-Bit-Opcode, 8-Bit-Operand); PIC18 haben 16-Bit-Flash. Beide speichern konstante Variablen im Flash; Einige PIC16-Compiler können angewiesen werden, Zeichenfolgen mit 2 x 7 Bit in jedes 14-Bit-Wort zu packen, was das Lesen beim Debuggen erschweren kann. Beide Familien haben vollständig getrennte Code- und Datenräume; Lesen Sie die Speicherkapitel eines beliebigen PIC16 / 18-Datenblatts für eine gute Erklärung. Ich kann das Problem "int/char funktioniert, int8/int16 nicht" nicht erklären, das macht überhaupt keinen Sinn - wie auch immer Sie sich entscheiden, ein char zu beschreiben, der Compiler sollte sich genau so verhalten.
Mir ist aufgefallen, dass der Grund, warum die Auto-Const-Arrays keine Fehler auslösten, darin besteht, dass ein const char[] eigentlich ein const char * ist; Der Zeiger befindet sich im RAM und die Daten, auf die er verweist, befinden sich im Flash. Der Zeiger kann jedes Mal neu geschrieben werden (um auf dasselbe Objekt in Flash zu zeigen), wenn die Funktion ausgeführt wird, ohne dass Probleme auftreten. Sie können auch versuchen, das char-v-uint8-Problem zu lösen, indem Sie ein #define anstelle eines typedef verwenden.

Ich denke, das Hauptproblem ist Ihre Erwartung, wie CONST mit diesem Compiler auf diesem Prozessor funktioniert. Diese Dinge sind keine Variablen, wie Sie von Ihrer Beschreibung zu erwarten scheinen. Sie sind sehr wahrscheinlich als Konstanten im Programmspeicher implementiert, der im Wesentlichen schreibgeschützt ist. Diese Dinge können zur Laufzeit nicht geändert werden. Der Fehler, den Sie erhalten, hängt wahrscheinlich mit dem Laufzeitcode zusammen, der versucht, in die CONST zu schreiben, nicht in die Definition der CONST.

Nichts davon erklärt, warum es an einigen Stellen in seinem Projekt funktioniert, an anderen jedoch nicht.
Er versucht jedoch nicht, den Wert zu ändern. Sie dürfen eine Konstante initialisieren; es ist ziemlich nutzlos, wenn du es nicht könntest.
@Dave: Es kann sein, dass er nur versucht, CONST zur Laufzeit in den fehlgeschlagenen Modulen zuzuweisen.
@user: Es ist überhaupt nicht klar, dass er nicht versucht, den Wert zur Laufzeit zu ändern.
Wir ändern den Wert nicht zur Laufzeit. Die Warnung zeigt auf eine Codezeile, und diese Zeile ist die Deklaration der Konstante.