Servus!
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 ;)
Bauform B. schrieb:> 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).
Was erwartest Du?
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
Ausgabe: int enum enum
Also in anderen Worten, bei `enum a x = A;`, is A nicht vom Typ `enum
a`, darum kann der Compiler da auch den Typ nicht checken.
Harald K. schrieb:> 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.
Niklas G. schrieb:> Code mit "g++" statt "gcc" kompilieren und "enum class" statt "enum"> hinschreiben
Das war ja klar :) make[1]: g++: No such file or directory;
Später gibt es tatsächlich nützliche neue Meldungen:
1
version.c:3: warning: "_GNU_SOURCE" redefined
2
3 | #define _GNU_SOURCE
3
|
4
<command-line>: note: this is the location of the previous definition
5
6
info_up.c:73:7: error: initializer-string for 'const unsigned char [128]' is too long [-fpermissive]
7
73 | "________________________________"
8
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9
74 | "___#_%&_()_+,-._0123456789___=__"
10
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11
75 | "@ABCDEFGHIJKLMNOPQRSTUVWXYZ_____"
12
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
13
76 | "_abcdefghijklmnopqrstuvwxyz_____";
14
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Au weia. Was macht der gcc daraus? Weiß der, dass das nie als String
benutzt wird optimiert die '\0' am Ende weg?
Aber solche Sachen finde ich doch übertrieben, das macht doch nur
Arbeit:
1
shm-view.c:200:15: error: invalid conversion from 'void*' to 'req_st*' [-fpermissive]
Bauform B. schrieb:> Da steht 'long int' und mein enum sollte wirklich nicht long sein.
Warum gibst du die Größe hier nicht einfach mit aus?
> printf ("%ld %ld\n", sizeof i32, sizeof (time_t));
(übrigens: der korrekte Format-Specifier für size_t ist %zu)
aber ja, der enum sollte die gleiche Größe wie int haben.
Bauform B. schrieb:> Au weia. Was macht der gcc daraus? Weiß der, dass das nie als String> benutzt wird optimiert die '\0' am Ende weg?
Er "optimiert" nicht, sondern es ist in C so, dass in so einem Fall kein
\0 angehängt wird, also:
1
charx[6]="Hallo";// hängt \0 an
2
chary[5]="Hallo";// erlaubt, hängt aber kein(!) \0 an
3
charz[4]="Hallo";// Fehler, zu wenig Platz
In C++ ist das anders geregelt. Da wird das \0 immer angehängt, d.h. der
zweite Fall ist dort auch ein Fehler, weil zu wenig Platz.
Bauform B. schrieb:> 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.
Bauform B. schrieb:> make[1]: g++: No such file or directory;
Kurioses Setup, lässt sich aber trivial beheben!
Bauform B. schrieb:> Au weia. Was macht der gcc daraus?
Schalt mal -Wextra ein:
1
warning: initializer-string for array of 'unsigned char' truncates NUL terminator but destination lacks 'nonstring' attribute (129 chars into 128 available) [-Wunterminated-string-initialization]
0-Byte wird also weggelassen weil das Array zu klein ist.
Bauform B. schrieb:> 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.
Markus F. schrieb:> in C sind enums typenlos
Sie sind nicht typenlos, sie sind Integer.