Do while C++ und Linux

Post Reply
Message
Author
Jitanoloco

Do while C++ und Linux

#1 Post by Jitanoloco »

Hallo,

ich bin neuer besutzer in diesem Forum und beschäftige mich nicht so lange mit Linux.
Ich habe ein Programm das für C++ geschrieben war in Linux umgeschrieben, nur scheint die Funktion einer do while Schleife anders zu sein. Die Schleife lässt sich garnicht starten.
Konkret geht es um folgende Schliefe, die als Anfangsbedingung den Wert !1 und als Stop- Wert den Wert !0 erhält. Tätsachlich lässt sich auch überprüfen dass sich diese Werte ändern nur lässt sich der Status der Schleife nicht beeinflussen. Die Werte werden aus dem Register eines Messinstrumentes mithilfe der Funktion ioctl ausgelesen.

do
{
i=0; res_ist=82.31045/1000;

while (!(ioctl(acam_fd16, 0x8)&0x0800))
{



{C3=ioctl(acam_fd16, 0x8)&0x0800; printf("FIFO empty? C3 %X\n",C3);}

ioctl(acam_fd16, WRITE_ACAM | 0x4, 0x0008);
FIFO0 = (ioctl(acam_fd16, 0x0)); //Read IFIFO1
Edge = (FIFO0>>17 & 0x00020000);
Chan = FIFO0>>26 & 0x00000001;
FIFO0 = FIFO0 & 0x0001ffff; {printf("FIFO0 %X\n" ,FIFO0);}
printf("ch %d hit# %d Edge %d \t%5.3fns\n\n ",Chan+1, i+1,Edge,(FIFO0)*82.31045/1000);
i++;
}

Die Äquivalenz zu boolschen Werten sind soweit ich weiss bei Linux ja True=1 und False=0, also sollte dies auch kein Problem machen.
Die Syntax zu ändern auf while (statement) do {expression} hilft auch nicht weiter. Hat jemand eine Idee was denn das Problem macht?
Danke

Euer Daniel

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#2 Post by Janka »

Ich ordne erstmal diesen Code.

Code: Select all

do 
{ 
  i=0; res_ist=82.31045/1000; 
 
  while (!(ioctl(acam_fd16, 0x8)&0x0800)) 
  {
    {C3=ioctl(acam_fd16, 0x8)&0x0800; printf("FIFO empty? C3 %X\n",C3);}
 
    ioctl(acam_fd16, WRITE_ACAM | 0x4, 0x0008); 
    FIFO0 = (ioctl(acam_fd16, 0x0)); //Read IFIFO1 
    Edge = (FIFO0>>17 & 0x00020000); 
    Chan = FIFO0>>26 & 0x00000001; 
    FIFO0 = FIFO0 & 0x0001ffff; {printf("FIFO0 %X\n" ,FIFO0);} 
    printf("ch %d hit# %d Edge %d \t%5.3fns\n\n ",Chan+1, i+1,Edge,(FIFO0)*82.31045/1000); 

    i++;
  }
Hat jemand eine Idee was denn das Problem macht?
Ja.

1. Das gegebene Codestück ist so unvollständig, dass man es nicht nachvollziehen kann. Wo sind die ganzen Variablen definiert?
2. Kompilieren lässt sich das erst recht nicht.
3. Kommentare, was es angeblich machen *soll*, sind ebenfalls Mangelware.
4. Der Rückgabewert von ioctl ist negativ für den Fehlerfall, sonst 0 oder positiv. Du prüfst den Fehlerfall aber gar nicht getrennt von deinem Fall ab, dass das Bit 0x0800 gesetzt ist.
Im Fehlerfall kommt aus deinem ioctl() eine negative Zahl raus, das ist in der Bitdarstellung irgendwas wie 0xfffffffffe
Mit ioctl()&0x800 wird daraus eine Zahl !=0, also *wahr*. Das drehst du mit ! um, also wird der Block innerhalb des while nicht aufgerufen.

Klär das erstmal, bevor du darüber spekulierst, ob "Linux" vielleicht True=0 definiert (C tut es nicht, gcc/g++ tut es auch nicht, und Linux erst recht nicht).

Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

Jitanoloco

#3 Post by Jitanoloco »

Hallo,

entschuldigung, soweit ich es nachvollziehen konnte, gibt es kein Problem bei der Variablendefinition, darum habe ich den Rest auch weggelassen. Wie gesagt das Programm lässt sich ohne Problem komplieren, die Schliefe lässt sich aber nicht starten.Dass ich nach den hypothetischen Unterschied zwischen C++ und ANSI C (Linux) gefragt habe, ist weil die Schleife unter C++ in dieser Form gestartet werden kann.

Ich füge mal das wichtigste hinzu.

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <time.h>
#include <signal.h>
#include <math.h>
#include <stdbool.h>

#define acam_device16 "/dev/acam_gpx_16"
#define acam_device32 "/dev/acam_gpx_32"

int main(int argc, char * argv[])
{
int acam_fd32;int acam_fd16;
unsigned int FIFO0;
unsigned int FIFO;
unsigned int FIFO1;

{
do
{
i=0;

while (!(ioctl(acam_fd16, 0x8)&0x0800))//Lese die while Bedingung aus einem bestimmten Register
{


ioctl(acam_fd16, WRITE_ACAM | 0x4, 0x0008);
FIFO0 = (ioctl(acam_fd16, 0x0)); //Lese aus einem
bestimmten Register
Edge = (FIFO0>>17 & 0x00020000);
Chan = FIFO0>>26 & 0x00000001;
FIFO0 = FIFO0 & 0x0001ffff; {printf("FIFO0 %X\n" ,FIFO0);}
printf("ch %d hit# %d Edge %d \t%5.3fns\n\n ",Chan+1, i+1,Edge,(FIFO0)*82.31045/1000);

i++;
}
}
}


Die Funktion (ioctl(acam_fd16, 0x8)&0x0800) liefert einen Wert von 1, wenn die Schleife anfangen soll und 0 wenn sie beendet werden soll. Daher die Bedingung while(!1):Also falls nicht true, soll das Instrument ausgelesen werden. Daran liegt vielleicht auch das Problem, was ich mit meiner Frage noch nachgehen wollte.
Da while mit booleans arbeitet, wird, soweit ich weiss der Wert 1 als true aufgefasst und der Wert 0 als false, kann also bei nicht true nicht gestartet werden. Gibt es keine Form dies unter ANSI C zu umgehen?

Man kann auch die Bedingung
while ((ioctl(acam_fd16, 0x8)&0x0800)!=1)
schreiben. Unter dieser Bedingung wird die Schleife sogar gestartet für den Fall 0 und 1! Sollte in dieser Form while den Wert 1 nicht mehr als boolean true auffassen, sondern als integer, und einfach dann starten wenn der vom Instrument ausgespuckte Wert mit 1 übereinstimmt?

Ich hoffe ich habe jetzt Missverständnisse beseitigt und danke nochmals.

Daniel

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#4 Post by Janka »

Jitanoloco wrote: Die Funktion (ioctl(acam_fd16, 0x8)&0x0800) liefert einen Wert von 1, wenn die Schleife anfangen soll und 0 wenn sie beendet werden soll.
Diese Funktion liefert 0x0800, falls der ioctl irgendwas zurückliefert, worin dieses Bit gesetzt ist. Also beispielsweise auch bei 0xffffffff, was -1 entspricht (Fehlerfall!).
Daher die Bedingung while(!1):Also falls nicht true, soll das Instrument ausgelesen werden.
Da hast du irgendwo einen Knoten im Gedankengang. Durch das ! wird die Schleife genau solange ausgeführt, wie das Bit aus 0x0800 *nicht* gesetzt ist. Ist das Bit gesetzt oder liefert ioctl einen Fehler zurück, wird die Schleife übergangen.
Gibt es keine Form dies unter ANSI C zu umgehen?
Diese Bedingung ist sowieso kaputt formuliert, weil da keine Fehlerbehandlung drin ist. Für die Ergebnisse von Funktionen, die drei verschiedene Pfade ansteuern, ist while denkbar ungeeignet. Dafür nimmt man for(;;), das ist viel übersichtlicher.

Code: Select all

int lese_schnittstelle&#40;void&#41;
&#123;
  int result;
  int count=0;
  for&#40;;;&#41;
  &#123;
    result=ioctl&#40;acam_fd16, 0x8&#41;;
    if &#40;result<0&#41;
    &#123;
      perror&#40;"Fehler bei ioctl&#40;&#41;"&#41;;
      return -1; /* mit Fehler raus aus der Funktion */
    &#125;
    if !&#40;result&0x800&#41; break; /* ioctl ok, aber Bit nicht &#40;mehr&#41; gesetzt, raus aus der Schleife */

    /* ioctl ok, Daten lesen. */
    ...
  &#125;

  /* Daten gelesen */
  return count
&#125;
Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

Jitanoloco

#5 Post by Jitanoloco »

Hallo,

danke nochmals.
Also ich habe den Fehlerfall eingebaut wie du beschrieben hast. Das ändert sowieso nichts, da die Funktion nie auf 0xffff gesetzt wird (keine Sorge ich hatte das ja auch ohne der Maske 0x800 überprüft), das Gerät liefert mir auch die richtige Werte für diese Funktion sobald er auch Messwerte bekommt. Technisch gibt es da kein Problem.
Nur will weder die while noch die for Schleife die Messwerte richtig aufsammeln. Noch lustiger, die for Schleife zählt sowohl für den Bit 0 und 1 gesetzt, also für 0 die richtigen Werte und für 1 irgendein Schman.(kein 0xffff).
Die for Schleife habe ich genau so geschrieben wie geschildert.Kann es sein, dass du ein Fehler bei if !(result0x800)gemacht hast? Das Ausführungszeichen muss in die Klammer rein, sonst kompiliert er es nicht.
Also paranoisch kann ich jetzt schon werden.In C++ funktioniert es doch so ohne Problem.

Ich schaue mal weiter,...
Danke nochmals

Daniel

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#6 Post by Janka »

Jitanoloco wrote:!(result0x800)gemacht hast?
Tatsächlich. Es muss (!(result&0x800)) heißen.
Das Ausführungszeichen muss in die Klammer rein, sonst kompiliert er es nicht.
Nein. Da müssen dann außen noch Klammern drum, denn (!result&0x800) ist dasselbe wie (!result)&0800, weil ! höherwertig als & ist. (Punkt vor Strich). Und letzteres ist wieder falsch.
Also paranoisch kann ich jetzt schon werden.In C++ funktioniert es doch so ohne Problem.
Mit C++ sollte das gar nichts zu tun haben. Da du vorhin C++ und Linux gegenübergestellt hast (als ob es bei Linux kein C++ gäbe), denke ich, dass es sich um ein Plattformproblem handelt, dass der ioctl eben nicht die richtigen Werte zurückgibt.

Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

Post Reply