Hallo zusammen,
wie das Thema schon sagt, ich möchte gerne meinen C-Code mit einer
Schleife verkürzen. Aber ich weiß keine Möglichkeit, die Ausgänge PDn
durch eine Variable zu ersetzen. Wie geht sowas?
Danke ;-)
Und zusätzlich, indem du _delay_ms mit einer Konstanten aufrufst.
Notfalls mit '1' aufrufen und in einer Schleifen ausführen. Steht aber
auch ausführlich in der Doku.
danke für die zahlreichen nachrichten. ich probiers mal aus ;-)
Skript Kiddy schrieb:> Irgendwo im io-header steht:>> #define PD0 0> #define PD1 1> #define PD2 2> ...
aha, dann kann ich also mit dieser methode jedem I/O pin einen
beliebigen namen geben?
Christian W. schrieb:> danke für die zahlreichen nachrichten. ich probiers mal aus ;-)>> Skript Kiddy schrieb:>> Irgendwo im io-header steht:>>>> #define PD0 0>> #define PD1 1>> #define PD2 2>> ...>> aha, dann kann ich also mit dieser methode jedem I/O pin einen> beliebigen namen geben?
Kannst du. Sollst du sogar.
Also jetzt nicht in deinem Lauflichtbeispiel, da ist das sinnlos. Aber
im Allgemeinen macht das schon Sinn
zb
1
#define RED_LED_DDR DDRD
2
#define RED_LED_PORT PORTD
3
#define RED_LED_BIT PD1
4
5
#define ERROR_LED_DDR DDRD
6
#define ERROR_LED_PORT PORTD
7
#define ERROR_LED_BIT PD0
8
9
10
intmain()
11
{
12
RED_LED_DDR|=(1<<RED_LED_BIT);
13
ERROR_LED_DDR|=(1<<ERROR_LED_BIT);
14
15
// alle LED aus (auf 1 schalten)
16
RED_LED_PORT|=(1<<RED_LED_BIT);
17
ERROR_LED_PORT|=(1<<ERROR_LED_BIT);
18
19
while(1){
20
21
if(irgendwas){
22
ERROR_LED_PORT&=~(1<<ERROR_LED_BIT);
23
}
24
25
RED_LED_PORT^=(1<<RED_LED_BIT);
26
_delay_ms(100);
27
}
28
}
wenn sich aus irgendeinem Grund die Notwendigkeit ergibt, dass zb die
rote LED an einen anderen Port wandern muss, dann brauchst du nur bei
den #define die neue Belegung eintragen und den Rest macht der Compiler.
Ausserdem ist viel klarer, was bei
RED_LED_PORT |= ( 1 << RED_LED_BIT );
passiert. Im Code steht hier explizit, dass da was mit der roten LED
(und nicht mit der Error LED) gemacht wird. Bei
PORTD |= ( 1 << PD1 );
müsste man erst mühsam raussuchen, dass hier etwas mit der roten LED
unternommen wird.
mampf schrieb:> Richtig. Bei PD1 und PD2 ist es ja noch nicht kritisch. Bei PD3> allerdings wird sicherlich nicht 3 stehen, sondern 4... Das ist doch der> Witz! ;-)
Falsch. Es wird die Bitnummer bezeichnet, nicht der Wert des Bits.
Luk4s K. schrieb:> mampf schrieb:>> Stimmt. Gut. Sorry.>> Fassen wir zusammen: Es gibt zwei Varianten Bits zu definieren
Eigentlich kann man das so nicht sagen.
Der Unterschied ist ganz einfach der
die einen haben Konstanten die die Bitnummer bezeichnen mit der die
einzelnen BIts angesprochen werden.
die anderen haben KOnstanten für die Werte, die an einen Port
geschrieben werden müssen um ein bestimmtes Bit zu verändern.
Es ist einfach nur eine andere Sichtweise darüber was wichtig ist:
die Bitnummer oder die Bitmaske
wobei man pikanterweise aus der Bitnummer die Maske leicht generieren
kann, während es nicht einfach ist aus der Bitmaske auf die Bitnummer zu
kommen. Wobei man fairerweise auch zugeben muss, dass man die Bitnummer
als solche eher selten braucht
> AVR-Stil:> Im Header:>
Das ist zwar gut gedacht und ich bin überzeugt du meinst auch das
Richtige, aber wenn man genauer hinsieht hast du da ziemlichen Unsinn
zusammengeschrieben.
Karl heinz Buchegger schrieb:> kommen. Wobei man fairerweise auch zugeben muss, dass man die Bitnummer> als solche eher selten braucht
Da die gleichen Header-Definitionen auch für Assembler verwendet werden,
und es bei AVRs Befehle mit Bitnummer gibt, ist die Angabe der Nummer an
Stelle der Maske ziemlich wesentlich.
Bei den STM32 ist es leider üblich, in den Headers Masken zu verwenden.
Allerdings können die Cortex-M3 über Bitbanding alle Steuerregister
bitweise ansprechen, wozu man aber an Stelle der Maske die Bitnummer
benötigt. Die Folge: ein ellenlanger ?: Konvertierungsmakro, der vom
Compiler wegoptimiert werden muss.
Ich verbessere (ist wohl beim copy&paste was schiefgelaufen)
Luk4s K. schrieb:> mampf schrieb:>> Stimmt. Gut. Sorry.>> Fassen wir zusammen: Es gibt zwei Varianten Bits zu definieren> AVR-Stil:> Im Header:>
so, damit die verwirrung bei mir nicht allzu groß wird, mach ich selbst
mal ein beispiel aus den oben genannten vorschlägen, vielleicht ist es
ja richtig (grins)
> _delay_ms(pause);
Man sieht leider im Codefetzen nicht wie pause definiert ist.
Schau dir das Thema Variablen vs. Konstanten beim Aufruf der
Delay-Funktionen noch in der avr-libc Doku an.
Die Übergabe von IO-Register und Pinnummer an eine Funktion kannst du in
diesem Beispiel abschauen:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#IO-Register_als_Parameter_und_Variablen
Stefan B. schrieb:>> _delay_ms(pause);>> Man sieht leider im Codefetzen nicht wie pause definiert ist.>> Schau dir das Thema Variablen vs. Konstanten beim Aufruf der> Delay-Funktionen noch in der avr-libc Doku an.>> Die Übergabe von IO-Register und Pinnummer an eine Funktion kannst du in> diesem Beispiel abschauen:>> http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#IO-Register_als_Parameter_und_Variablen
Das ist kein Codefetzen, mehr davon gibt es noch gar nicht, ist nur so
ein Versuch, ich würde schreiben: uint8_t pause = 100;
trallala schrieb:> Christian W. schrieb:>> // Strings zusammensetzen>> PORT = "LED" & n & "PORT";>> BIT = "LED" & n & "BIT";>> das is ma geil XD
warum? weils geil ist oder weils nicht geht? ;)
nein nicht bös gemeint .. aber das sieht nunmal bissel krass aus ^^
und ich frage mich wie du auf strings kommst ??
ich sage mal ganz grob so gehts definitiv nicht !!
aber denk mal selbst nach ...
is die beste schule
Frag mal deinen Compiler. Wie kommst du dazu, dass Variablen Strings
sind? Oder dass du den Namen einer Variablen per String ändern kannst.
Und Strings kannst du so auch nicht zusammensetzen, wenn es mit Strings
ginge.
Christian W. schrieb:> vielleicht ist es> ja richtig (grins)
naja.
1. du definierst LED_... von 1 bis 8, lässt aber die Schleife
von 0 bis 7 laufen
2. Du hast bei "LED" & n & "PORT" die Tiefstriche vergessen.
3. Das ist kein C, selbst mit den obigen Fehlern korrigiert.
Christian W. schrieb:> Das ist kein Codefetzen, mehr davon gibt es noch gar nicht, ist nur so> ein Versuch, ich würde schreiben: uint8_t pause = 100;
Geht nicht. Kompiliert zwar aber du bekommst prinzipbedingt keine
genauen Delays. Nimm
#define pause 100
_delay_ms(pause);
oder lesbarer (Geschmackssache, Makros in Großschrift und sinnvoller
Name):
#define PAUSE_100MS 100
_delay_ms(PAUSE_100MS);
ok, hab ne verständnisfrage. warum gehts mit einer variable "pause"
ungenauer als mit define?
prinzipiell ist es ja schön dass mich einige hier auf meine fehler
hinweisen, aber leider eine erklärung bzw. ein codebeispiel dann fehlt,
das würde ich mir eigentlich erwarten und wäre auch sinn der sache,
ansonsten würde ich hier nicht um hilfe bitten.
sorry
christian
hab hier mal ein codebeispiel angehängt das soweit funktioniert, ohne
compilerfehler.
nur was ist, wenn ich wegen des platinenlayouts nicht bei einem port
bleiben kann, sondern led 1-4 auf portd habe, und led 5-8 auf portc?
außerdem funktioniert das laufen da unten sowieso nicht, da immer nur
die erste led leuchtet
da weiß ich dann nicht mehr weiter...
christian
Christian W. schrieb:> ok, hab ne verständnisfrage. warum gehts mit einer variable "pause"> ungenauer als mit define?
weil _delay_ms() ein Makro ist und eine Konstante "erwartet". Wenn du
eine Variable nutzt, dann muß der Compiler hier Code einsetzen welcher
auch mit variablem (veränderlichen) Pausenzeiten läuft. Und dieser Code
ist per definition ungenauer.
_delay_ms(10) erzeugt eine Verzögerung von exakt 10ms, abgestimmt auf
den im Projekt angegebenen CPU-Takt (z.B. "#define F_CPU 3686400UL").
Torsten K. schrieb:> Christian W. schrieb:>> ok, hab ne verständnisfrage. warum gehts mit einer variable "pause">> ungenauer als mit define?>> weil _delay_ms() ein Makro ist und eine Konstante "erwartet". Wenn du> eine Variable nutzt, dann muß der Compiler hier Code einsetzen welcher> auch mit variablem (veränderlichen) Pausenzeiten läuft. Und dieser Code> ist per definition ungenauer.
Ungenauer ist der nicht, kann er ja nicht sein, sonst würde der Compiler
beim Optimieren ja den Sinn verändern.
Er läuft nur langsamer und dürfte um Faktor 10..20 größer sein, da die
_delay-Makros mit Fließkomma formuliert sind und damit die ganze
Mathebibliothek hinterherziehen.
Sven P. schrieb:> Ungenauer ist der nicht, kann er ja nicht sein, sonst würde der Compiler> beim Optimieren ja den Sinn verändern.
Ungenauer nicht im mathematischen Sinn, sehr wohl aber bei dem, was
damit erreicht werden soll: der Laufzeit.
aha deswegen liefen meine früheren delays immer unterschiedlich lange,
weil ich variablen verwendet habe...
kann mir bei meinem obigen code noch jemand weiterhelfen? ich möchte
speziell in die for-schleife etwas einbauen, dass dem gerecht wird, wenn
ich einige leds an portc, und einige an portd habe. mir gehts darum zu
verstehen wie ich veränderbare variablen, statt "PD5, PD6, usw..."
verwende.
Sowas macht man, wenn es denn unbedingt sein muss, idealerweise mit
Arrays.
Die Arrays (mal einfach gesagt, Du hättest zwei stück) sind so groß, wie
Du Schritte hast. In einem kommt die Portadresse in den anderen die
verwendete Bitmaske. Jetzt kannst Du mittels Arrayindex die Ports der
"Reihe nach" ansprechen.
Christian W. schrieb:> durchschieben geht ja nur bedingt, wenn ich 4 leds an port d, und 4 leds> an port c habe. oder? (grübel...)>> hätte da jemand ein kurzes codebeispiel?
Das Dilemme ist, dass das in diesem Fall nicht mehr so einfach ist, wenn
man es komplett so formulieren möchte, dass man alles per #define
variabel halten möchte und möglichst kurz halten will (sprich mit einer
Schleife arebitet)
Das liegt daran, dass du hier indirekt adressieren musst. Du willst die
i-te LED leuchten lassen, und aus diesem i muss man irgendwie auf den
Port und das zu setzende Bit kommen. Das ist aber fundemantal etwas
anderes als das was man bei der überwiegenden Mehrzahl der Fälle hat, in
denen der Port bzw die Bitmaske mehr oder weniger fix ist und nicht
indirekt über ein i adressiert wird.
Eine Möglichkeit ist zb. wie bereits gesagt, mit einem Array zu
arbeiten. Eigentlich müssten es 3 sein: Eines für das zu konfigurierende
DDR Register, eines für das Port Register an dem ausgegeben wird und
eines für die Bitmaske.
for(i=0;i<8;++i)// die benötigten Port Bits auf 1 (=Ausgang) schalten
51
*Ddr[i]|=Mask;
52
53
while(1)
54
{
55
for(i=0;i<8;i++)
56
{
57
*Port[i]|=Mask;
58
_delay_ms(100);
59
*Port[i]&=~Mask;
60
}
61
}
62
63
return0;
64
}
Das einzige was jetzt noch fix ist, ist die Anzahl der LED. Will man die
auch noch variabel halten, dann könnte man auch das noch machen.
Aber du siehst schon, der Aufwand ist nicht unbeträchtlich. Deshalb hab
ich auch weiter oben gesagt, dass das 'Ansprechen einzelner LED' bei
einem Luaflicht nicht sehr sinnvoll ist, auch wenn es möglich ist.
Wenn du das meiste davon noch nicht verstehst, dann ist das kein
Beinbruch. Um das im Detail zu verstehen muss man schon ein wenig Übung
haben. So wie hier geschrieben ist das nichts, was ich von einem Neuling
erwarten würde.
Was du aber tun solltest: Besorg dir ein C Buch.
Was du hier geschrieben hast
1
....
2
3
#define LED_8_PORT PORTD
4
#define LED_8_BIT PC4
5
6
// Lauflicht-Schleife
7
for(uint8_tn=0;n<8;n++)
8
{
9
// Strings zusammensetzen
10
PORT="LED"&n&"PORT";
11
BIT="LED"&n&"BIT";
12
13
....
zeigt eigentlich sehr deutlich, dass dir hier viele Grundlagen fehlen
und dir insbesondere nicht klar ist, was #define eigentlich wirklich
macht.
Kauf dir ein C-Buch! Du wirst es brauchen. Eine Sprache wie C kann man
nicht durch Versuch&Irrtum und durch zusammenfragen in Foren lernen.
Wenn man nicht systematisch an die Feinheiten herangeführt wird, wird
immer mit seinem Halbwissen auf die Schnauze fallen und in der Situation
sein, dass einzelne Details in einem Fremdprogramm für einen einfach
keinen Sinn ergeben, während sie für jemanden mit einem soliden
Wissensunterbau völlig glasklar sind.
zwar funktioniert das codebeispiel wegen vieler compilerfehler nicht,
aber endlich mal eine brauchbare antwort und eine aussagekräftige
erklärung der lage.
(error: invalid operands to binary | (have 'int' and 'volatile uint8_t
*'))
übrigens hab ich schon diverse internetseiten in php programmiert, was
ja in gewisser weise ähnlichkeit mit c hat, da versuche ich hin und
wieder, die php logik in den c code zu übertragen, was anscheinend nicht
100% klappt :-D
weil das zusammensetzen von strings aus mehreren bestandteilen läuft
seit jahren einwandfrei mit php... (beispiel weiter oben...)
danke ;-)
Christian W. schrieb:> zwar funktioniert das codebeispiel wegen vieler compilerfehler nicht,
Das war mein Fehler.
Ich habs nicht durch den Compiler gejagt sondern direkt hier im Forum
eingetippt.
Mask ist ja auch ein Array, also muss man auch dort natürlich mit dem
Index ran
1
...
2
3
intmain(void)
4
{
5
uint8_ti;
6
7
for(i=0;i<8;++i)// die benötigten Port Bits auf 1 (=Ausgang) schalten
8
*Ddr[i]|=Mask[i];
9
10
while(1)
11
{
12
for(i=0;i<8;i++)
13
{
14
*Port[i]|=Mask[i];
15
_delay_ms(100);
16
*Port[i]&=~Mask[i];
17
}
18
}
19
20
return0;
21
}
> weil das zusammensetzen von strings aus mehreren bestandteilen läuft> seit jahren einwandfrei mit php... (beispiel weiter oben...)
Tja.
Das Problem ist, dass du erst mal gar keine Strings hast.
Zweitens sind die Variablennamen nach dem Compilieren gar nicht mehr
vorhanden. Das heißt du kannst dich aus Prinzip in C schon mal gar nicht
per Programm auf Variablen beziehen, deren Namen du erst zur Laufzeit
festlegen willst. Wenn du so etwas brauchst, dann führt der Weg immer
über ein Array.
Wie gesagt: #define macht etwas völlig anderes, als was du vermutest.
Christian W. schrieb:> ja danke auch für die antwort...! (kopfschüttel)
Am besten wäre es, wenn du dir ein C-Buch kaufst und das durcharbeitest.
Dann lernst du C von der Pike auf und musst nicht durch Probieren oder
Begutachtung Anderer herausfinden, ob etwas funktioneren kann oder
nicht.
Gruß Skriptkiddy
> Wie gesagt: #define macht etwas völlig anderes, als was du vermutest.
Schön und gut... Nur was macht #define? Das es was anderes macht hab ich
nun schon 2x gehört, aber kein einziges Mal eine Erklärung dazu... ^^
Für euch ist es ein leichtes mal 2 Sätze hinzuschreiben.
Christian W. schrieb:> achso! na jetzt versteh ich das auch. ist doch ganz einfach wenn mans> weiß :-D
Exakt.
Vieles ist in C eigentlich gar nicht so schwer.
Das Problem: Wenn man immer nur Teile vor sich hat und immer nur in
Einzelteilen lernt, dann hat man viele Einzelteile die scheinbar nicht
zusammenpassen. Genau aus diesem Grund wirst du immer wieder hören: Kauf
dir ein C Buch.
Denn ein Buch hat einen enormen Vorteil: Es bringt dich systematisch von
den einfachen Dingen zu den schwierigeren Dingen. Das Buch ist so
aufgebaut, dass jedes Kapitel auf dem vorhergehenden beruht und du in
kleineren Schritten an das Wissen herangeführt wirst.
In einem Forum wird dir die ungeschminkte Wahrheit über C um die Ohren
geschlagen. Und die ist in C manchmal auf den ersten Blick gar nicht so
schmeichelhaft. Warum gewisse Dinge in C genau so sind, wie sie sind,
erschliesst sich einem erst dann, wenn man das große Ganze sieht. Denn
dann sieht man plötzlich, das das was zunächst unlogisch erschien,
eigentlich genau so ist, damit eine gewisse Systematik gewahrt bleibt
und wenn man die Systematik kennt, folgt das vermeintlich Unlogische
sofort daraus und ist überhaupt nicht mehr unlogisch.
zb #define
oder ganz allgemein alle Zeilen, die mit # anfangen.
Die haben mit C bzw. dem Compiler nur soviel zu tun, dass sie
Anweisungen an den Preprozessor sind. Der ist zwar ein obligatorischer
Bestandteil des Compilier-Prozesses, ist aber eigentlich nichts anderes
als ein Texteditor, der vor dem Compiler läuft und den Programmtext für
den Compiler aufbereitet. Und dieser Texteditor wird pikanterweise durch
Kommandos gesteuert (eben jene Zeilen, die mit # beginnen), die im Text
selber eingebettet sind, den er bearbeiten soll.
Und das alles und noch vieles vieles mehr, steht in jedem noch so
grindigem C-Buch. Und zwar im Detail. Viel besser und viel
ausführlicher, mit all den kleinen Details auf die in Foren gerne
vergessen wird, als irgendjemand dir das in einem Forum beschreiben
könnte oder auch nur beschreiben wollte.
Klaus Wachtler schrieb:> http://www.wachtler.de/ck/5_Praeprozessor.html
Hallo Klaus.
Nicht das ich Kritik üben möchte.
Aber könntest du in deinem Tut an dieser Stelle
> Verhindern kann man den Fehler nur, indem man die Parameter nicht> beim Aufruf manipuliert, sondern gegebenenfalls vorher oder nachher:>> #define max(a,b) ( a>b ? a : b );> /* ... */> ++i;> gross = max(i,gross);> /* ... */
noch einen Absatz einfügen. So irgendwas nach diesem Muster:
Aus dem vorgenannten sieht man auch, dass Makros so ihre Tücken haben
und es daher für denjenigen der ein Makro verwendet unter Umständen sehr
wichtig sein kann, zu wissen dass er es mit einem Makro zu tun hat.
Unter anderem aus diesem Grund hat es sich schon in den C-Anfängen von
Anfang an eingebürgert, dass Makronamen immer vollständig in
Grossbuchstaben geschrieben werden und auch umgekehrt Namen nur in
Grossbuchstaben ausschliesslich für Makros reserviert sind. Dies ist
eine der wenigen Konventionen, die sich weltweit durchgesetzt haben und
es gibt keinen wie auch immer gearteten Grund mit dieser Konvention zu
brechen. In realem Code würde man daher ein derartiges Makro so
schreiben
1
#define MAX(a,b) ( (a)>(b) ? (a) : (b) )
damit an der verwendenden Stelle
1
gross=MAX(i,gross);
eindeutig klar ist, dass es sich hier bei MAX um ein Makro handelt und
nicht etwa um eine reale Funktion und man daher bei den Makroargumenten
etwas vorsichtig sein muss.
NB: Ach ja. den ; am Makroende besser wegmachen.
Karl heinz Buchegger schrieb:> noch einen Absatz einfügen. So irgendwas nach diesem Muster:
Jetzt wo du es sagst, vermisse ich es auch.
Dachte eigentlich, ich hätte es drin stehen.
Erstmal habe ich es nicht direkt eingefügt, sondern auf meine
TODO-Liste gesetzt. Ich muß an dem Ding schon lange mal einiges
renovieren, dann kommt es mit rein.
Nachtrag: Die Renovierung stagniert, weil ich das früher immer als
LaTeX geschrieben habe und die HTML-Version jeweils mit latex2html
generiert hatte. Das hat aber einige Problemchen und scheint
ziemlich tot zu sein, sodaß ich auf etwas anderes umsteigen will.
Bisher konnte ich mich nicht durchringen, was ich als Ersatz nehmen
soll (auch mangels Druck, solange ich den Stoff nicht brauche).
Vielleicht verzichte ich auch ganz auf HTML und mache nur noch PDF,
da brauche ich nicht viel ändern.
Klaus Wachtler schrieb:> Karl heinz Buchegger schrieb:>> NB: Ach ja. den ; am Makroende besser wegmachen.>> Peinlich und erledigt.
Ach was. Simpler Tippfehler. Kann vorkommen.
Zumal man die Auswirkungen eines ; im Makro nur unter bestimmten
Bedingungen sieht.
Ich hatte das letzte Woche bei einem Kollegen, der sich bei (sinngemäss)
if( a < c )
j = MAX( a, b );
else
j = 0;
über ein 'else without if' freuen durfte. Er hats aber selbst in ein
paar Minuten gefunden. Pikanterweise existiert das Makro (war eine
Verpackung für strncpy) schon seit mindestens 15 Jahren (weiter reichen
die SVN Aufzeichnungen nicht zurück) und offenbar hatte noch nie jemand
Probleme damit. Wir haben dann beschlossen, irgendwann in nächster Zeit,
wenn der Stress mit der anstehenden Release weg ist, das mal zu
bereinigen. Solche Dinge im Nachhinein zu ändern ist insbesondere bei
großem Code gefährlich und das wollen wir jetzt nicht machen. Zum
Jahreswechsel müssen wir auf den Markt, keine Experimente zum jetzigen
Zeitpunkt :-) Code der unter Umständen möglicherweise anderen Code in
seiner Bedeutung verändert, wie das ja bei Makros durchaus möglich ist,
können wir uns jetzt nicht leisten.
Wir haben die Situation dann mit einem
if( a < c ) {
j = MAX( a, b );
}
else
j = 0;
vorerst bereinigt
Karl heinz Buchegger schrieb:> Wir haben die Situation dann mit einem> if( a < c ) {> j = MAX( a, b );> }> else> j = 0;
Wobei ich ohnehin mit den Mund fusselig rede, daß man generell
for, if, else und Konsorten mit ganzen Blöcken schreiben sollte.
Dafür scheinst du aber auch nicht empfänglich zu sein...
Klaus Wachtler schrieb:> Wobei ich ohnehin mit den Mund fusselig rede, daß man generell> for, if, else und Konsorten mit ganzen Blöcken schreiben sollte.> Dafür scheinst du aber auch nicht empfänglich zu sein...
Und meine IDE ersetzt "fehlende" Klammern automatisch beim speichern /
reformatiren von Source, sehr nützlich ;)
Da mag ich es dann doch wenn Programmiersprachen solch ein Konstrukt
erst gar nicht erlauben :)
Karl heinz Buchegger schrieb:> eine Experimente zum jetzigen> Zeitpunkt :-) Code der unter Umständen möglicherweise anderen Code in> seiner Bedeutung verändert,
Na ist doch kein Problem ihr habt ja bestimmt Unittests die euch sagen
ob noch alles so klappt wie vorher ;P duck und weg
na gut, da ich nun weiß wo meine schlauheit aufhört (grins) hätt ich mal
ne frage. gibts so einen c-lernkurs im internet oder irgendwo als pdf?
danke
christian
Viele.
Meiner (ohne daß er der beste sein muß -weil er eigentlich nur
als Begleitung zu einer Vorlesung gedacht war-, aber ich kenne
ihn halt):
http://www.wachtler.de/ck/index.html
Karl heinz Buchegger schrieb:> damit an der verwendenden Stelle gross = MAX(i,gross);> eindeutig klar ist, dass es sich hier bei MAX um ein Makro handelt und> nicht etwa um eine reale Funktion und man daher bei den Makroargumenten> etwas vorsichtig sein muss.
Wenn man auf gcc eingeschossen ist und dessen Erweiterungen verwenden
kann, kann man min/max Makros auch ohne Nebeneffekte schaffen. Hier mal
aus dem Linux Kernel zitiert:
1
/*
2
* min()/max()/clamp() macros that also do
3
* strict type-checking.. See the
4
* "unnecessary" pointer comparison.
5
*/
6
#define min(x, y) ({ \
7
typeof(x) _min1 = (x); \
8
typeof(y) _min2 = (y); \
9
(void) (&_min1 == &_min2); \
10
_min1 < _min2 ? _min1 : _min2; })
11
12
#define max(x, y) ({ \
13
typeof(x) _max1 = (x); \
14
typeof(y) _max2 = (y); \
15
(void) (&_max1 == &_max2); \
16
_max1 > _max2 ? _max1 : _max2; })
Dabei werden x und y nur einmal evaluiert, Sachen wie max(x++,y)
funktionieren wie erwartet. Abgesehen von der zusätzlichen
Typüberprüfung ist obiges identisch mit dem Beispiel aus der gcc-Doku
zur Erweiterung "typeof".