Forum: PC-Programmierung Formatierte Ausgabe - ioctl() Ergebnis


von Matthias (Gast)


Lesenswert?

Guten Tag.

Weil ich es für ein anderes Projekt benötige, habe ich mich in das Thema 
'Zugriff auf Devices' eingelesen und ein paar schöne, funktionierende 
Code-Beispiele gefunden.

Allerdings gibt es eine Sache, die ich nicht verstehe. Nachstehend 
benutze ich ioctl(---,CDROM_GET_CAPABILITY)

Bei der formatierten Ausgabe der Ergebnisse, werden zwei '!!' benötigt, 
damit die Ausgabe Erfolg hat. In dem Buch steht aber leider nicht wieso.

Normalerweise negiert ein '!' meines Wissens nach ein Ergebnis. Bei 
zweien müsste hieraus somit wieder das ursprüngliche Ergebnis 
resultieren.

Lasse ich die beiden '!!' aber weg, meldet sich der Compiler mit einem 
Segmentation fault.
1
const char *entscheidung[] = {"Nein","Ja"};
2
3
fd = open("/dev/sr0",O_RDONLY | O_NONBLOCK); 
4
5
if((ergebnis = ioctl(fd, CDROM_GET_CAPABILITY)) == -1){
6
  perror("ioctl(CDROM_GET_CAPABILITY) ");
7
}  
8
9
printf("\nCDROM-Eigenschaften\n");
10
printf("CD-R      :      %s\n", entscheidung[!!(ergebnis & CDC_CD_R)]);
11
printf("CD-RW     :      %s\n", entscheidung[!!(ergebnis & CDC_CD_RW)]);
12
printf("DVD       :      %s\n", entscheidung[!!(ergebnis & CDC_DVD)]);
13
printf("DVD-R     :      %s\n", entscheidung[!!(ergebnis & CDC_DVD_R)]);
14
printf("DVD-RAM   :      %s\n\n", entscheidung[!!(ergebnis & CDC_DVD_RAM)]);

von Peter II (Gast)


Lesenswert?

was liefert denn
1
ergebnis & CDC_CD_R

zurück? Eine Zahl.

Was liefert das zurück:
1
!(ergebnis & CDC_CD_R)

das könnte man jetzt schon verwenden, aber dafür müsste man ja/nein im 
Array vertauschen.

Da man das scheinbar nicht will kommt einfach noch ein ! davor.

Für sinnvoll lesbar halte ich den code aber nicht.
1
printf("CD-R      :      %s\n", entscheidung[(ergebnis & CDC_CD_R)?0:1]);

ist für mich lesbarer.

von Rolf M. (rmagnus)


Lesenswert?

Matthias schrieb:
> Bei der formatierten Ausgabe der Ergebnisse, werden zwei '!!' benötigt,
> damit die Ausgabe Erfolg hat. In dem Buch steht aber leider nicht wieso.
>
> Normalerweise negiert ein '!' meines Wissens nach ein Ergebnis.

(es heißt entweder "meines Wissens" oder "meinem Wissen nach").

> Bei zweien müsste hieraus somit wieder das ursprüngliche Ergebnis
> resultieren.

Nun, dein Array hat zwei Elemente, nämlich das mit dem Index 0 und das 
mit dem Index 1. Wenn du nun schreibst:

> ergebnis & CDC_CD_R

dann kommt bei dieser Operation nur dann ein gültiger Index raus, wenn 
CDC_CD_R 0 oder 1 ist. Es hat aber vermutlich einen anderen Wert. Der 
Operator ! interpretiert den übergebenen Wert als booleschen Wert, wobei 
0 false entspricht und jeder andere Wert true. Wenn das wiederum als 
Integer benutzt wird, wird aus false 0 und aus true 1. Das heißt also, 
daß das ! aus dem "entweder 0 oder CDC_CD_R" ein "entweder 1 oder 0" 
macht. Da das aber dann invertiert ist, kommt noch ein zweites ! davor, 
damit es wieder richtig rum ist. Das, was Peter geschrieben hat, ist 
eine leichter verständliche Alternative. Er hat allerdings versehentlich 
0 und 1 vertauscht.

Peter II schrieb:
> Für sinnvoll lesbar halte ich den code aber nicht.

Immerhin ist er im Gegensatz zu deinem korrekt. Aber ich nutze da auch 
lieber den Operator ?: als die doppelte Invertierung.
Ich würde aber auch gleich noch dieses String-Array sparen und die 
Strings direkt an die Stelle schreiben. Das macht es noch etwas 
lesbarer:
1
printf("CD-R      :      %s\n", ergebnis & CDC_CD_R ? "Ja" : "Nein");

von Matthias (Gast)


Lesenswert?

>(es heißt entweder "meines Wissens" oder "meinem Wissen nach").

"meines Wissens nach" ist eine mögliche Schreibweise.

>dann kommt bei dieser Operation nur dann ein gültiger Index raus, wenn
>CDC_CD_R 0 oder 1 ist. Es hat aber vermutlich einen anderen Wert. Der
>Operator ! interpretiert den übergebenen Wert als booleschen Wert, wobei
>0 false entspricht und jeder andere Wert true. Wenn das wiederum als
>Integer benutzt wird, wird aus false 0 und aus true 1. Das heißt also,
>daß das ! aus dem "entweder 0 oder CDC_CD_R" ein "entweder 1 oder 0"
>macht. Da das aber dann invertiert ist, kommt noch ein zweites ! davor,
>damit es wieder richtig rum ist.

Perfekt. Vielen Dank für die ausführliche Erklärung.
Wenn es um bedingte Anweisungen geht, würde ich ebenfalls auf die hier 
von Euch beiden gewählte Kurzsschreibweise zurückgreifen.

Ich habe jetzt noch einmal nachgeschlagen. Der Grund meiner Verwirrung 
lag darin, dass ich den logischen !-Operator vorher nicht richtig 
verstanden habe. Er negiert nicht nur, sondern tut dies auch selbst auf 
Grund einer Bedingung, dass war mir neu. Ich habe gedacht, dass er 
einfach nur negiert, sobald man ihn einsetzt.

> Für sinnvoll lesbar halte ich den code aber nicht.
Hierüber lässt sich trefflich streiten, gerade bei 'C'. Ich denke es 
gibt kaum schlechten Code, denn vielmehr schlecht auskommentierten Code.

>printf("CD-R      :      %s\n", ergebnis & CDC_CD_R ? "Ja" : "Nein");
Kann man natürlich hardcoded machen. Ist halt die Frage, was man gerade 
bevorzugt, bessere Lesbarkeit vs. Wartbarkeit.

von Rolf M. (rmagnus)


Lesenswert?

Matthias schrieb:
>>(es heißt entweder "meines Wissens" oder "meinem Wissen nach").
>
> "meines Wissens nach" ist eine mögliche Schreibweise.

Möglich ist sie - aber eben auch falsch:
http://www.duden.de/rechtschreibung/meines_Wissens

> Ich habe jetzt noch einmal nachgeschlagen. Der Grund meiner Verwirrung
> lag darin, dass ich den logischen !-Operator vorher nicht richtig
> verstanden habe. Er negiert nicht nur, sondern tut dies auch selbst auf
> Grund einer Bedingung, dass war mir neu. Ich habe gedacht, dass er
> einfach nur negiert, sobald man ihn einsetzt.

Im Prinzip tut er das ja auch, aber er interpretiert den übergebenen 
Wert als booleschen Wert (mit der Zuordnung 0 -> false, alles andere -> 
true) und negiert nicht jedes Bit einzeln. Das würde der Operator ~ 
machen.

>>printf("CD-R      :      %s\n", ergebnis & CDC_CD_R ? "Ja" : "Nein");
> Kann man natürlich hardcoded machen. Ist halt die Frage, was man gerade
> bevorzugt, bessere Lesbarkeit vs. Wartbarkeit.

Was mich an der anderen Variante vor allem stört, sind die magischen 
Arrray-Indizes 0 und 1, deren Bedeutung man nicht an der Stelle ihrer 
Benutzung erkennen kann. Davon abgesehen finde ich auch, daß der lange 
Ausdruck zwischen den eckigen Klammern die Lesbarkeit stark erschwert. 
Wenn man denn unbedingt statt direkte Strings Zeiger haben will, dann 
lieber so:
1
const char * const ja   = "Ja";
2
const char * const nein = "Nein";
3
// ...
4
printf("CD-R      :      %s\n", ergebnis & CDC_CD_R ? ja : nein);

von Matthias (Gast)


Lesenswert?

Mal eine andere Frage, ioctl() selbst betreffend.

Der Grund mich mit obiger Funktion zu beschäftigen liegt in einem 
Projekt, welches sich mit Socket Programmierung und dem TCP-Stack 
beschäftigt.

Hierbei stieß ich auf ioctl(), den Request'SIOCGIFHWADDR' und die 
Struktur 'ifreq', in welcher die Requestdaten gespeichert werden.

In meinen Büchern fand ich wenig, bis gar nichts über dieses Thema, 
weshalb ich erst einmal in den Manpages nachgesehen habe.

In der Manpage zu ioctl() war der Hinweis auf die Liste aller Requests 
'ioctl_list'.

Was mir aber gefehlt hat war die Verbindung zur Struktur ifreq, darüber 
gab es keinerlei Hinweise.

Habe ich da etwas übersehen?

Anders gefragt, ich benutze ioctl() und irgendeinen x-beliebigen 
Request, woher bekomme ich die Info, welche Struktur ich nutzen muss, um 
die Rückgabe zu speichern?

von Matthias (Gast)


Lesenswert?

SORRY...

Ich hatte die Output-Datei nur halb geoeffnet und habe gerade gesehen, 
dass neben der Spalte, in der die Requests aufgelistet werden, noch 
weitere Daten folgen.

-erledigt-

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.