Eigentlich wollte ich fragen, ob der gcc vielleicht noch mehr enum-Warnungen liefern könnte. Das wäre nett, aber beim minimalen Testfall fehlt jetzt eine, die ich wirklich vermisse:
1
#include<stdio.h>
2
#include<time.h>
3
4
typedefenumfoo_enum{
5
FOO_NONE,
6
FOO_A,
7
FOO_B
8
}foo_enum;
9
10
intenum_test(foo_enump1)
11
{
12
inti32;
13
14
printf("%ld %ld\n",sizeofi32,sizeof(time_t));
15
i32=time(NULL);
16
if(p1==FOO_A){
17
p1=time(NULL);
18
}
19
switch(p1){
20
caseFOO_A:
21
printf("A\n");
22
break;
23
case42:
24
printf("B\n");
25
break;
26
caseFOO_NONE:
27
printf("Sorry.\n");
28
break;
29
}
30
return0;
31
}
1
enum_test.c: In function 'enum_test':
2
enum_test.c:16:10: warning: conversion from 'time_t' {aka 'long int'} to 'int' may change value [-Wconversion]
3
16 | i32 = time (NULL);
4
| ^~~~
5
enum_test.c:20:4: warning: enumeration value 'FOO_B' not handled in switch [-Wswitch]
6
20 | switch (p1) {
7
| ^~~~~~
8
enum_test.c:24:4: warning: case value '42' not in enumerated type 'foo_enum' [-Wswitch]
9
24 | case 42:
10
| ^~~~
Zeile 16: reine Routine, Zeile 20 und 24 finde sehr nützlich. Aber Zeile 18 "p1 = time (NULL);" ist angeblich total ok?
Mein gcc kennt immerhin schon -std=c2x, der ist doch nicht völlig veraltet?
1
gcc (Debian 12.2.0-14+deb12u1) 12.2.0
2
Copyright (C) 2022 Free Software Foundation, Inc.
Vor 20 Jahren bekam jemand eine Warnung vom IAR, wie ich sie auch gerne hätte:
Beitrag "Enum Warnung"
Edit: na klar, time() von heute = 1772093657, passt noch in int32_t ;)
Aber Zeile
18 "p1 = time (NULL);" ist angeblich total ok?
Wie sieht der Prototyp der Funktion time aus? Hast Du mal in time.h nachgesehen?
Da dürfte was stehen wie
1
time_ttime(time_t*);
Der Funktion einen Nullpointer zu übergeben ist legitim, den Rückgabewert einem int zuzuweisen, kann auch vollkommen legitim sein (je nachdem, wie in Deinem System time_t definiert ist).
Naja, die Sache ist halt, enum konstanten sind nicht vom sie definierenden enum typ, sondern (meistens) ein int. Und wenn man den Typ explizit angibt, wird der enum gleich ganz als solchen behandelt...
1
#include<stdio.h>
2
3
intmain(){
4
{
5
enuma{A};
6
printf("%s %s %s\n",
7
_Generic(A,enuma:"enum",int:"int"),
8
_Generic((enuma)A,enuma:"enum",int:"int"),
9
_Generic(((enuma)A)+1,enuma:"enum",int:"int")
10
);
11
}
12
13
/*
14
{ // error: '_Generic' specifies two compatible types
Der Funktion einen Nullpointer zu übergeben ist legitim, den
Rückgabewert einem int zuzuweisen, kann auch vollkommen legitim sein (je
nachdem, wie in Deinem System time_t definiert ist).
Was erwartest Du?
Die gleiche Warnung wie für Zeile 16, da funktioniert es doch: "conversion from 'time_t' {aka 'long int'} to 'int'..." Da steht 'long int' und mein enum sollte wirklich nicht long sein.
OK, die Warnung würde praktisch nicht viel nützen und auf einem System mit 64-bit int würde es garnicht auffallen. Aber hier müsste die Warnung doch zwangsläufig kommen und das irritiert mich.
Aber solche Sachen finde ich doch übertrieben, das macht doch nur
Arbeit:
Naja, C++ ist da strikter und lässt zwar Konvertierungen von Zeigern nach void* ohne Cast zu, aber von void* in was anderes muss man explizit casten. Allerdings braucht man void* in C++ auch nicht so oft, wenn man es richtig macht.
Aber solche Sachen finde ich doch übertrieben, das macht doch nur
Arbeit:
Das ist Typsicherheit... void* sollte man halt so wenig wie möglich verwenden. In C ist es nicht vermeidbar, in C++ größtenteils schon. Einen Cast hinzuzufügen, auch als Warnung an den Leser, dass hier etwas potenziell gefährliches passiert, schadet nicht.
Vielen Dank für die lehrreichen Beiträge. An dieser Stelle gebe ich einfach mal auf. Einmal, weil es noch so viel zu lernen gibt, aber auch, weil seit gestern Mittag wieder andere Sachen viel wichtiger sind :(