Warnung bei enum und case

Für Fehler in Lazarus, um diese von anderen verifizieren zu lassen.
Antworten
Mathias
Beiträge: 6955
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Warnung bei enum und case

Beitrag von Mathias »

Bei folgendem Code bekomme ich eine Warnung, bei case eine Abfrage fehlt, dies wäre korrekt.

Code: Alles auswählen

type
  tenum = (a, b, c);

  procedure test(e: tenum);
  begin
    case e of
      //a: begin
      //  WriteLn(a);
      //end;
      b: begin
        WriteLn(b);
      end;
      c: begin
        WriteLn(c);
      end;
    end;
  end;
So kommt keine Warnung, was io. ist.

Code: Alles auswählen

type
  tenum = (a, b, c);

  procedure test(e: tenum);
  begin
    case e of
      a: begin
        WriteLn(a);
      end;
      b: begin
        WriteLn(b);
      end;
      c: begin
        WriteLn(c);
      end;
    end;
  end;
Mache ich aber einen Sprung in der enum Deklaration, bekomme ich eine Warnung wie im ersten Beispiel.

Code: Alles auswählen

type
  tenum = (a, b = 10, c); // Hier ein Sprung

  procedure test(e: tenum);
  begin
    case e of
      a: begin
        WriteLn(a);
      end;
      b: begin
        WriteLn(b);
      end;
      c: begin
        WriteLn(c);
      end;
    end;
  end;

begin
  test(a);
  test(b);
  test(c);
end.
Ist dies so gewollt, oder ist dies ein Bug ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

kirchfritz
Beiträge: 227
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win11 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Re: Warnung bei enum und case

Beitrag von kirchfritz »

Code: Alles auswählen

type
  tenum = (a, b = 10, c); // Hier ein Sprung
Was will uns der Autor damit sagen? Was soll eine Wertzuweisung (b =10) innerhalb einer Enumeration, oder ist (b = 10) ein BooleanAusdruck?
Als Mensch habe ich hier ein Verständnisproblem. Kein Wunder also, dass sich der Kompiler auch schwer tut. :)

Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1629
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: Warnung bei enum und case

Beitrag von corpsman »

*g*

Als reiner Pascal'er sieht das Komisch aus, die enum Definition sehe ich oft bei C-Code (was nicht heisen soll dass ich das Gut finde, sondern nur erklärt woher es kommt). So können die Enum Constanten direkt weiter gegeben werden. Ich denke der Compiler "bläht" den Raum des Enums von 0..2 nun auf 0..10 auf und prangert deswegen unten an, dass da noch welche fehlen.

Korrekt würde ich empfehlen eine Routine zu schreiben, welche den Enum explizit in einen Zahlenwert umrechnet, damit hast du dann auch alles klar definiert und bist nicht darauf angewiesen, dass der Compiler schon das richtige tut ...

alla

Code: Alles auswählen

function enumToint(const e:TEnum):Integer;
begin
result := -1 ; // Fehler ?
case e of
a:result := 0;
b:result := 10;
c:result := 1;
end;
end;
--
Just try it

wp_xyz
Beiträge: 5188
Registriert: Fr 8. Apr 2011, 09:01

Re: Warnung bei enum und case

Beitrag von wp_xyz »

corpsman hat geschrieben: Di 2. Jul 2024, 11:05 Ich denke der Compiler "bläht" den Raum des Enums von 0..2 nun auf 0..10 auf [...]
Nein, von 0 bis 11, denn die Abfolge der zugeordneten Integerwerte springt bei b=10 auf 10 und läuft von da ab weiter:

Code: Alles auswählen

program Project1;
type
  TEnum = (a, b = 10, c);
begin
  WriteLn(ord(a));
  WriteLn(ord(b));
  WriteLn(ord(c));

  ReadLn;
end. 

{output:
0
10
11
} 
Eine sinnvolle Anwendung davon wären die Monate, um dem Januar die 1 statt der 0 zuzuweisen, so wie in den FormatSettings benötigt:

Code: Alles auswählen

type
  TMonth = (mJan=1, mFeb, mMar, mApr, mMay, mJune, mJuly, mAug, mSept, mOct, mNov, mDec);
...
  WriteLn(FormatSettings.LongMonthNames[ord(mJune)]);  // ---> output: Juni

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6848
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Warnung bei enum und case

Beitrag von af0815 »

a=0,b=10,c=11 wenn man es sich mit ord(e) ausgeben lässt. Damit ist der Bereich 1-9 eine Grauzone die nicht verwendet ist. Für case sind aber die Genzen damit 0 unten und 11 oben. 1-9 sind daher ganz einfach unbehandelte Fälle. Zumindest IMHO.
Ich finde der Compiler hat da schon recht.
Und man braucht bei enums nichts umrechnen, die Werte = Ordinalzahlen kann man sich immer ausgeben lassen. Und Achtung mit den Graubereichen, ich habe die schon mal durch einen Fehler verwendet. for i:= ord(a) to ord(c) ist da so ein Kandidat :-)
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Benutzeravatar
theo
Beiträge: 10920
Registriert: Mo 11. Sep 2006, 19:01

Re: Warnung bei enum und case

Beitrag von theo »

Komisch, ich sehe diese Warnung nicht.
Free Pascal Compiler version 3.2.2-r0d122c49 [2024/03/10] for x86_64

Grundsätzlich kann man ein case auch mit "else" oder "otherwise" abschliessen, dann dürfte die Warnung verschwinden, wenn es nur darum geht.
Oder {$warn 6060 off}

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6848
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Warnung bei enum und case

Beitrag von af0815 »

theo hat geschrieben: Di 2. Jul 2024, 11:58 Grundsätzlich kann man ein case auch mit "else" oder "otherwise" abschliessen
Den Weg gehe ich meistens, was ich eigentlich nie mache, ist die Warnung global abzuschalten. (Ausnahme die für das Inline)
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Benutzeravatar
theo
Beiträge: 10920
Registriert: Mo 11. Sep 2006, 19:01

Re: Warnung bei enum und case

Beitrag von theo »


wp_xyz
Beiträge: 5188
Registriert: Fr 8. Apr 2011, 09:01

Re: Warnung bei enum und case

Beitrag von wp_xyz »

theo hat geschrieben: Di 2. Jul 2024, 11:58 Grundsätzlich kann man ein case auch mit "else" oder "otherwise" abschliessen
Und dann im else/otherweise Zweig eine Exception feuern. Denn im Eifer des Gefechts fügt man oft neue Elemente zur Aufzählung hinzu und vergisst die case-Anweisungen zu erweitern

Mathias
Beiträge: 6955
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Warnung bei enum und case

Beitrag von Mathias »

Als reiner Pascal'er sieht das Komisch aus, die enum Definition sehe ich oft bei C-Code (
Genau so ist es, da sieht man es sehr viel.
Generell werden bei C sehr viel enum anstelle von const/#define verwendet. Dies mach auch Sinn. Man vermeidet so auh, das man ungültiges übergibt.

So geht wirklich nur dies hier:

Code: Alles auswählen

type
  TColorEnum = (red, green , blue);

  procedure test(e: TColorEnum);
  begin
    WriteLn(e);
  end;
begin
  test(red);
end.
Würde man es mit const machen, kann man sehr einfach ungültige Werte übergeben.

Code: Alles auswählen

const
  rot = 0;
  greun = 1;
  blau = 2;
  
  procedure test(c: byte);
  begin
    WriteLn(c);
  end;
  
  test(123);
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten