Hallo ! Ich habe folgende Frage : mit welchem Programmcode ( in C ) kann ich einen beschriebenen uint16_t in 2 uint8_t umwandeln ? außerdem besteht dann die Frage : wie kann ich dann die zwei einzelnen bytes ansprechen ? ( ich bräuchte praktisch das high byte und das low-byte vom integer) Danke im Voraus, Jakov
Gast
#2655440
1 | |
2 | |
sollte die sichere Variante sein. Probier es mal aus.
Andere Idee: (weiss aber nicht, wie man das beim AVR umsetzen kann) Man definiert eine 16-Bit Variable und legt die fest auf bestimmte RAM-Adressen. Danach definiert man 2 8-Bit Variablen und legt die auf die selben (!) 8-Bit Adressen. Der Compiler spuckt zwar eine Warning aus, aber die Aufteilung ist sehr elegant. Schreibe den 16-Bit Wert und lese 2x die 8-Bit Werte. Beim 8051 mit RIDE sieht das dann so aus: data at 0x10 unsigned int Ergebnis; // belegt Adressen 0x10 und 0x11 data at 0x10 unsigned char HighByte, LowByte; // Reihenfolge muss man bei seinem Compiler testen... // jetzt kann man zum Beispiel die Timer-Reloads so machen: Ergebnis = (65536-Zeit_in_us); // nur die Subtraktion wird gerechnet TL0 = LowByte; // dauert nur 2us TH0 = HighByte; // und es wird nix gerechnet tschuessle Bernhard
Gast
#2655533
Bernhard Spitzer schrieb: > (weiss aber nicht, wie man das beim AVR umsetzen kann) Wie kann man das in irgendeinem Controller in C umsetzen? Eine Möglichkeit wäre, dass man Zeiger erzeugt und denen die entsprechenden Adresse zuweist. Da ist die Gefahr aber groß, dass der Compiler die Adresse überschreibt. >data at 0x10 unsigned int Ergebnis; Ich würde zwar von mir sagen, dass ich C gut kann, aber 'data' und 'at' ist mir da nie untergekommen. Was soll das machen?
Gast
#2655534
Naja, dann lieber gleich eine Union, die ist für sowas gedacht und der Compiler meckert nicht.
Gast
#2655544
1 | |
2 | |
3 | |
4 | |
5 | |
oder so Ähnlich. Sowas habe ich gerade mit XCode ausprobiert und es funktioniert. Ist ziemlich getrickst, aber wahrscheinlich schneller als meine erste Variante.
Blub schrieb: > Naja, dann lieber gleich eine Union, die ist für sowas gedacht und der > Compiler meckert nicht. Und wenn du dann beim Portieren des mal die Endianess gewechselt wird? Das Einzige was gleichermaßen auf Little und Big Endian funktionieren wird ist: Dussel schrieb: > uint8_t var1=(uint8_t)(var16&0xFF); > uint8_t var2=(uint8_t)((var16>>8)&0xFF); Gruß Oliver
Dussel schrieb: > uint16_t *zvar16=&var16; > uint8_t *zvar1=(uint8_t *)var16; > uint8_t *zvar2=(uint8_t *)(var16+1); > var1=*zvar1; > var2=*zvar2; Das ist falsch. Du solltest schon richtigen Code posten. So ein Müll nützt Niemandem. So könnte man es über deine Idee auf Little Endian machen:
1 | |
2 | |
3 | |
Gruß Oliver
Gast
#2655705
Oliver J. schrieb: > So könnte man es über deine Idee auf Little Endian machen: Erstens ist es nicht meine Idee, sondern die von Bernhard Spitzer. Ich habe sie nur Standard-C tauglich aufgeschrieben. Oliver J. schrieb: > Das ist falsch. Du solltest schon richtigen Code posten. So ein Müll > nützt Niemandem. Zweitens: Dann schreib mal, was daran falsch ist, wenn es so funktioniert. Drittens: Was ist in deinem Beispiel anders, als in meinem, außer dass ich es ausführlicher mache?
Dussel schrieb: > Oliver J. schrieb: >> Das ist falsch. Du solltest schon richtigen Code posten. So ein Müll >> nützt Niemandem. > Zweitens: Dann schreib mal, was daran falsch ist, wenn es so > funktioniert. Das funktioniert so nicht. zvar16 ist ein pointer vom typ uint16_t *, dieser + 1 zeigt nicht auf das nächste Byte.
Gast
#2655715
1 | |
2 | |
3 | |
4 | |
5 | |
Mein Fehler. In der zweiten und dritten Zeile soll es natürlich zvar16 heißen. Wenn ich nicht noch einen Schreibfehler drinhabe, müsste es aber so funktionieren. Mit dem +1 funktioniert es bei mir. AVRStudio habe ich nicht hier, aber mit XCode geht es, wenn ich statt uint16_t ein unsigned short int und statt uint8_t ein unsigned char nehme. Den funktionierenden Code habe ich mal angehängt. Vielleicht habe ich mich beim Abschreiben ja nochmal vertan.
Mit zvar16+1 erwischst du niemals das High-Byte. Schau dir mal diese beiden Pointer an:
1 | |
Gruß Oliver
Gast
#2655724
Oliver J. schrieb: > Mit zvar16+1 erwischst du niemals das High-Byte. Das kann sein. C hat so viele 'Gemeinheiten'. Trotzdem wüsste ich noch gerne, warum es funktioniert.
Dussel schrieb: > Trotzdem wüsste ich noch > gerne, warum es funktioniert. Ich kann mir beim besten Willen nicht vorstellen, dass es mit deinem Code wirklich funktioniert. Gruß Oliver
Gast
#2655729
Tut mir leid für das Durcheinander, aber jetzt habe ich es: Die Klammern um das zvar16+1 sind zu viel. Die hatte ich in der ersten Version fälschlicherweise drumgemacht und dann übernommen. Danke. Wenigstens war mein gedachter Ansatz richtig. Im Programm habe ich es ja auch automatisch richtig gemacht, nur dann falsch übertragen.
Gast
#2655730
Blub schrieb: > Naja, dann lieber gleich eine Union, die ist für sowas gedacht und der > Compiler meckert nicht. Nein, es ist in Standard-C ausdrücklick verboten, einen anderen Eintrag aus einer Union zu lesen, als derjenige, der zuletzt einen Wert erhalten hat. Die Zeigerrechnerei ist insofern fatal, als dass Zeiger keine Adressen im Speicher sind. Das predige ich etliche Jahre und kriege dafür immer nur müdes Lächeln. Und zwar meistens genau so lange, bis der Betroffene auf die Fresse gefallen ist und stundenlang debuggt hat. Es gibt außer Big- und Little-Endian dann auch noch Middle-Endian. Könnte außerdem mit Alignment einen Unfall geben. Der richtige Weg ist ja schon genannt worden: Simple Arithmetik mit Schieben. Das optimiert jeder brauchbare Compiler ohnehin auf irgendeinen Speicherversatz. Und das funktioniert sogar portabel.
Gast
#2655735
Oliver J. schrieb: > Ich kann mir beim besten Willen nicht vorstellen, dass es mit deinem > Code wirklich funktioniert. Probier es doch aus. Du hast doch sicher einen C(++)-Compiler rumliegen. Für C musst du eben iostream.h einfügen und die Dateiendung in .C ändern.
Dussel schrieb: > Oliver J. schrieb: >> Ich kann mir beim besten Willen nicht vorstellen, dass es mit deinem >> Code wirklich funktioniert. > Probier es doch aus. Du hast doch sicher einen C(++)-Compiler rumliegen. > Für C musst du eben iostream.h einfügen und die Dateiendung in .C > ändern. lol
Gast
#2655865
Sven P. schrieb: > Blub schrieb: >> Naja, dann lieber gleich eine Union, die ist für sowas gedacht und der >> Compiler meckert nicht. > Nein, es ist in Standard-C ausdrücklick verboten, einen /anderen/ > Eintrag aus einer Union zu lesen, als derjenige, der zuletzt einen Wert > erhalten hat. Aber was ist denn dann die Anwendung für eine Union? > Die Zeigerrechnerei ist insofern fatal, als dass Zeiger keine Adressen > im Speicher sind. Das predige ich etliche Jahre und kriege dafür immer > nur müdes Lächeln. Das interessiert mich jetzt aber doch: Was meinst Du damit und worauf willst Du damit hinaus?
Dosmo schrieb: > Aber was ist denn dann die Anwendung für eine Union? Wie wäre es mit Speicher sparen?
Dosmo schrieb: > Das interessiert mich jetzt aber doch: Was meinst Du damit und worauf > willst Du damit hinaus? Zeiger enthalten im Prinzip eine Adresse. Wenn man aber Integer-Werte zu ihnen hinzu addiert oder von ihnen subtrahiert, dann ist der neue Wert des Zeigers von der Breite des Datentyps abhängig, auf den der Zeiger zeigt. Bsp:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
Gruß Oliver
> Blub schrieb: >> Naja, dann lieber gleich eine Union, die ist für sowas gedacht und der >> Compiler meckert nicht. > Nein, es ist in Standard-C ausdrücklick verboten, einen /anderen/ > Eintrag aus einer Union zu lesen, als derjenige, der zuletzt einen Wert > erhalten hat. Na denn erzähl mir mal wie man sonst an die Bits eines floats rankommt um sie zB über I2C zu senden.
Martin Wende schrieb: > Na denn erzähl mir mal wie man sonst an die Bits eines floats rankommt > um sie zB über I2C zu senden. Über einen Pointer-Cast. http://snipplr.com/view/8806/ Gruß Oliver
Gast
#2656019
Martin Wende schrieb: > Na denn erzähl mir mal wie man sonst an die Bits eines floats rankommt > um sie zB über I2C zu senden. In Standard-C theoretisch garnicht. Wenn du allerdings solcherlei Low-Level-Programmierung anstellen möchtest, musst du ja ohnehin in das Handbuch deines Compilers gucken. Insofern erübrigt sich die Portabilität dann. Das geht soweit, dass z.B. im C-Standard von 1999 nichtmal spezifiziert ist, wie genau ein 'long double' auszusehen hat. Bei Unions kommt erschwerend dazu, dass es bei Bitfeldern keinerlei Garantie hast, wie die Bits im Speicher angeordnet sind (Endianness, Überlappung). Bei Strukturen kann am Ende aufgefüllt werden. Um das zu umgehen, kann man z.B. ein Compiler-spezifisches 'packed'-Attribut mitgeben. Da wären wir dann wieder beim Compiler-Handbuch... Thomas: Grammatikalisch in die Hose gegangen, da hast du Recht. Also nochmal: >> Nein, es ist in Standard-C ausdrücklick verboten, einen /anderen/ >> Eintrag aus einer Union zu lesen, als denjenigen, der zuletzt einen Wert >> erhalten hat. Ansonsten habe ich natürlich alles falsch verstanden, meine Erfahrungen sind Einbildung und du bist der einzig wahre Heilsbringer. In Ordnung? Gut. Dosmo: Ein Beispiel hast du gesehen, nämlich dass Feldweise adressiert wird. Wenn ein Feld vier Zeichen lang ist, rückt man im Speicher halt vier Zeichen weiter, wenn man '1' zum Zeiger addiert. Weiterhin ist die Zuordnung zwischen Zeiger und Ganzzahl nicht spezifiziert. Es ist zwar erlaubt, einen Zeiger in eine Ganzzahl zu wandeln und wieder zurück, es ist aber nicht festgelegt, dass diese Ganzzahl in irgendeinen der Integer-Typen passen muss (ISO/IEC 9899:TC2 6.3.2.3 Abs. 6)! Wenn du eine Ganzzahl in einen Zeiger umwandelst, muss dieser Zeiger weder richtig ausgerichtet sein, noch auf ein gültiges Objekt zeigen. Das insbesondere ist relevant, wenn man einen uint8_t* auf einen uint16_t* umbiegt. Möglicherweise zeigt der dann nämlich garnicht mehr auf den gewünschten uint16_t. Auch da hilft das Compiler-Handbuch weiter. Im übrigen, und das habe ich ja angedeutet, erschließt sich mir der Sinn hinter der Pfriemelei nicht. Der arithmetische Weg mit dem Schiebe-Operator ist gut lesbar, portabel und wird praktisch von jedem Compiler optimiert.
Gast
#2656025
Sven P. schrieb: > Im übrigen, und das habe ich ja angedeutet, erschließt sich mir der Sinn > hinter der Pfriemelei nicht. Der arithmetische Weg mit dem > Schiebe-Operator ist gut lesbar, portabel und wird praktisch von jedem > Compiler optimiert. Den habe ich ja direkt geschrieben. Danach ging es nur noch um die philosophische Überlegung, ob man es auch anders machen kann.
Sven P. schrieb: > Der arithmetische Weg mit dem Schiebe-Operator ist gut lesbar, > portabel und wird praktisch von jedem Compiler optimiert. Und selbst wenn es nicht zu 100% optimal übersetzt wird und ne überflüssige Instruktion bleibt, ist es allemal besser als die Adresse einer lokalen Variablen zu nehemn!
Gast
#2656288
Johann L. schrieb: > Und selbst wenn es nicht zu 100% optimal übersetzt wird und ne > überflüssige Instruktion bleibt, ist es allemal besser als die Adresse > einer lokalen Variablen zu nehemn! Bei dir weiß ich ja, dass du ein Fachmann bist (sic) -- betonst du absichtlich die lokale Variable? Falls dem so ist, dann weil deren Adresse nicht konstant ist und es dadurch zu Zeigerrechnerei kommt, wohingegen bei einer globalen Variable meistens direkt lds/sts erzeugt werden kann?
Gast
#2656290
Dussel schrieb: > Danach ging es nur noch um die > philosophische Überlegung, ob man es auch anders machen kann. Wie kommt es, dass es Dir notwendig erscheint, die "Überlegung" als eine "philosophische" zu bezeichnen, Dussel?
Gast
#2656297
Sven P. schrieb: > > Dosmo: > Ein Beispiel hast du gesehen, nämlich dass Feldweise adressiert wird. > Wenn ein Feld vier Zeichen lang ist, rückt man im Speicher halt vier > Zeichen weiter, wenn man '1' zum Zeiger addiert. Okay, das meinst Du. Dazu am Rande: Eine Sache, über die ich mal gestolpert bin, war auf dem MSP430 ein UART-Empfangs-Ringpuffer, aus dem ich ein uint16_t auslesen wollte. Da hab ich auch die Adresse des Datums feucht-fröhlich als uint16_t* gecastet, ausgelesen und prompt folgt ein Address-Trap! Was war passiert? Das Telegram lag an einer ungerade Adresse im Puffer, daher war das auszulesende uint16 auch an einer ungeraden Adresse, und auf diese kann man (beim MSP430 und vielen anderen) keinen 16Bit-Zugriff machen. Es half nur byteweise lesen und Bits schieben.
Gast
#2656298
Dosmo schrieb: > [...] Schau doch mal im Assembler-Listing, was dann tatsächlich draus wurde. Sicherlich auch wieder nur Speicherversatz, also ein Byte-Zugriff oder ein Byte-Swap im Arbeitsregister. Aber du siehst ja auch, manche Leute wollen das einfach nicht verstehen.
Gast
#2656300
Sven P. schrieb: > Johann L. schrieb: >> Und selbst wenn es nicht zu 100% optimal übersetzt wird und ne >> überflüssige Instruktion bleibt, ist es allemal besser als die Adresse >> einer lokalen Variablen zu nehemn! > Bei dir weiß ich ja, dass du ein Fachmann bist (sic) -- betonst du > absichtlich die lokale Variable? > > Falls dem so ist, dann weil deren Adresse nicht konstant ist und es > dadurch zu Zeigerrechnerei kommt, wohingegen bei einer globalen Variable > meistens direkt lds/sts erzeugt werden kann? Vielleicht sollte man an der Stelle noch folgendes erwähnen: Es gibt Architekturen, bei denen die CPU-Register nicht im Speicheradressraum liegen, d.h. nicht per Adresse/Zeiger (bzw. load/store) zugreifbar sind. Lokale Variablen liegen aber gerne in Registern. Wenn man eine lokale Variablen dann mit Adresse/Register-Zugriff benutzt, muß diese dazu dann auf den Stack ausgelagert werden, was den Code auch nicht gerade effizienter macht.
Gast
#2656301
Dosmo schrieb: > Vielleicht sollte man an der Stelle noch folgendes erwähnen: > Es gibt Architekturen, bei denen die CPU-Register nicht im > Speicheradressraum liegen, d.h. nicht per Adresse/Zeiger (bzw. > load/store) zugreifbar sind. Lokale Variablen liegen aber gerne in > Registern. Wenn man eine lokale Variablen dann mit > Adresse/Register-Zugriff benutzt, muß diese dazu dann auf den Stack > ausgelagert werden, was den Code auch nicht gerade effizienter macht. Ja, das ist im C-Standard berücksichtigt, sodass man von einer Variablen, die mit 'register' vereinbart wurde, keine Adresse erhalten kann. An Johann L. dachte ich dann, weil er knietief im AVR-GCC steckt.
Gast
#2656397
Dussel schrieb: > uint16_t *zvar16=&var16; > uint8_t *zvar1=(uint8_t *)var16; > uint8_t *zvar2=(uint8_t *)(var16+1); > var1=*zvar1; > var2=*zvar2; und wenn du dir deinen code 3 monate später anschaust, weisst du sofort was du da geamcht hast? so einfach wie möglich, so kompliziert wie nötig...
Gast
#2656414
Dussel-Fänger schrieb: > Dussel schrieb: >> Danach ging es nur noch um die >> philosophische Überlegung, ob man es auch anders machen kann. > > Wie kommt es, dass es Dir notwendig erscheint, die "Überlegung" als eine > "philosophische" zu bezeichnen, Dussel? Philosophisch als Ausdruck dafür, dass es nicht um die praktische Anwendung geht, sondern nur um das 'wissen Wollen'. Was natürlich auch nicht uninteressant ist. funky schrieb: > Dussel schrieb: >> uint16_t *zvar16=&var16; >> uint8_t *zvar1=(uint8_t *)var16; >> uint8_t *zvar2=(uint8_t *)(var16+1); >> var1=*zvar1; >> var2=*zvar2; > > und wenn du dir deinen code 3 monate später anschaust, weisst du sofort > was du da geamcht hast? so einfach wie möglich, so kompliziert wie > nötig... Der Code ist ja sowieso falsch, aber ich denke, dass ich mir die Funktion des Codes rekonstruieren könnte. Davon abgesehen würde ich ausnahmsweise mal einen Kommentar setzen, wenn ich sowas verwenden würde…
Gast
#2656468
Dussel schrieb: > Dussel-Fänger schrieb: > >> Dussel schrieb: >>> Danach ging es nur noch um die >>> philosophische Überlegung, ob man es auch anders machen kann. > >> Wie kommt es, dass es Dir notwendig erscheint, die "Überlegung" als eine >> "philosophische" zu bezeichnen, Dussel? > Philosophisch als Ausdruck dafür, dass es nicht um die praktische > Anwendung geht, sondern nur um das 'wissen Wollen'. Was natürlich auch > nicht uninteressant ist. In diesem Zusammenhang ist die Verwendung des Attributs "philosophisch" gänzlich unangebracht, ja sogar falsch. Avanti Dilettanti, Dussel!
Gast
#2656485
Tut mir leid, ich verstehe kein Italienisch. Davon abgesehen gibt es die umgangssprachliche Bezeichnung philosophisch für 'einfach nur des Wissens wegen' oder 'aus der Freude am Wissen'. Jetzt übersetze die Wörter, aus denen Philosophie gebildet ist noch und du wirst feststellen, dass man das hier durchaus gebrauchen kann. Davon abgesehen: Wenn es dir solche (geistigen) Schmerzen bereitet, kannst du es auf deine Verantwortung auch durch ein beliebiges anderes Wort ersetzen.
Dosmo schrieb: > Sven P. schrieb: >> Johann L. schrieb: >>> Und selbst wenn es nicht zu 100% optimal übersetzt wird und ne >>> überflüssige Instruktion bleibt, ist es allemal besser als die Adresse >>> einer lokalen Variablen zu nehemn! >> Bei dir weiß ich ja, dass du ein Fachmann bist (sic) -- betonst du >> absichtlich die lokale Variable? Lokal ist eigentlich nicht zutreffend. Es geht um auto-Variablen bzw. um solche, die nicht im Static Storage liegen. In den meisten Anwendungen ist lokal Deckungsgleich mit auto, aber dass ist natürlich nicht zwingend. >> Falls dem so ist, dann weil deren Adresse nicht konstant ist und es >> dadurch zu Zeigerrechnerei kommt, wohingegen bei einer globalen Variable >> meistens direkt lds/sts erzeugt werden kann? Über Adressen von Variablen im Static Storage weiß der Compiler, daß sie unveränderlich sind. Zur Adressberechnung kann er also — bei AVR — einfach LDI Instruktionen verwenden. Das geht, obwohl er selbst die Adresse nicht kennt: Die Adresse wird erst vom Linker/Locator festgelegt.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
kann von avr-gcc also so übersetzt werden:
1 | |
2 | |
3 | |
4 | |
Ist x hingegen auto:
1 | |
2 | |
3 | |
4 | |
5 | |
dann sieht der Code etwas anders aus:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
Beide Funktionen wurden mit % avr-gcc -S -Os -mmcu=atmega8 übersetzt, und es ist nix mehr daran zu optimieren bis auf eine unnötige Instruktion im zweiten Listing. Natürlich sind die beiden Funktionen nicht gleichwertig; die erste ist zum Beispiel nicht reentrant. Aber das Beispiel zeigt, daß man sich mit der Adressbildung von auto-Variablen schnell den Code aufpusten kann — insbesondere, wenn es ohne Not geschieht wie oben; und dann möglicherweise noch verstreut über den ganzen Code und abgesehen von bereits genannten Problemen wie Endianess, Alignment, Aliasing Rules, Type Punning, Wart- und Lesbarkeit, Portierbarkeit, etc. Um die Adresse zu nehmen, muss der Compiler das Auto auf dem Stack (im Frame der Funktion) anlegen. Um es im Frame anlegen zu können, muss ein Frame angelegt werden. Um einen Frame anzulegen, wird ein Framepointer benötigt. Um einen Framepointer zu haben, muss er einen initialisieren. Um einen initialisieren zu können, muss er die betreffenden Register (hier Y) sichern und wieder herstellen. Y ist im weiteren Verlauf der Funktion an den Framepointer gebunden und kann nicht mehr für andere Zwecke verwendet werden. Bei AVR mit seiner üppigen Ausstattung an Zeigerregistern ist das besonders ungünstig. > Vielleicht sollte man an der Stelle noch folgendes erwähnen: > Es gibt Architekturen, bei denen die CPU-Register nicht im > Speicheradressraum liegen, d.h. nicht per Adresse/Zeiger (bzw. > load/store) zugreifbar sind. Ein Compiler wird niemals nicht die Adressberechnung einer Variablen auf die Speicheradresse eines GPRs abbilden oder umgekehrt. Das wäre absoluter Hack und ein schwerer technischer Fehler. GCC wird niemals auf ein Register über dessen Speicheradresse zugreifen oder Adressberechnung eines Auto entsprechend abbilden. Greift man dennoch über (*((unsigned char volatile*) 10)) auf R10 zu, so weiß der Compiler nicht, daß es um einen Zugriff aus R10 geht. Das Verhalten ist komplett undefiniert.
Gast
#2656533
Dussel schrieb: > gibt es die umgangssprachliche Bezeichnung philosophisch > für 'einfach nur des Wissens wegen' oder 'aus der Freude am Wissen'. Dieser angeblich umgangssprachliche Gebrauch von 'philosphisch' ist frei erfunden. Nomen est omen, Dussel!
Gast
#2656588
Dussel-Ex schrieb: > Dussel schrieb: >> gibt es die umgangssprachliche Bezeichnung philosophisch >> für 'einfach nur des Wissens wegen' oder 'aus der Freude am Wissen'. > > Dieser angeblich umgangssprachliche Gebrauch von 'philosphisch' ist frei > erfunden. Ich habe eine Quelle gefunden (es gibt mindestens eine), wo das auch so verstanden wird. Trotzdem habe ich es falsch verstanden (nicht erfunden). Also muss ich zugeben, dass ich es falsch benutzt habe.
Sag doch einfach "aus Wissbegier" oder "aus rein akademischem Interesse".
Gast
#2656622
Johann L. schrieb: > Sag doch einfach "aus Wissbegier" oder "aus rein akademischem > Interesse". Ja, danke. Sowas meinte ich und hatte halt dafür 'philosophisch' im Kopf. 'Aus Freundschaft zum Wissen'. Es sollte aber längst jedem klar sein, was gemeint war.
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.