hallo
ich programmiere in c
geht das irgendwie, auf Variablen zuzugreifen, wenn sie im main
definiert sind.
also ich will zB im interrupt.c einer funktion func(int i), die variable
i übergeben, welche im main definiert ist.
Dazu brauchst Du eine globale Variable.
Eine "Variable in main" ist eine lokale Variable der Funktion main, auf
die kannst Du nicht zugreifen.
Schreib einfach die Deklaration vor main(), damit wird die Variable
global.
Also statt
@ sepp (Gast)
>ich programmiere in c
Und hast mal wieder vergessen, in ein C-Buch zu schauen.
>geht das irgendwie, auf Variablen zuzugreifen, wenn sie im main>definiert sind.
Klar, in main.c
>also ich will zB im interrupt.c einer funktion func(int i), die variable>i übergeben, welche im main definiert ist.
Nö. Dafür hat der liebe Gott bzw. die Jungs K&R die globalen Variablen
erfunden, welche außerhalb einer Funktion definiert werden. Und beim
Thema Interrupt sollte man das Thema volatile und atomarer Zugriff
nicht vergessen.
Stefan K. schrieb:> Schreib einfach die Deklaration vor main(), damit wird die Variable> global.
Unvollständig.
Wenn er aus dem Interrupt drauf zugreifen will muß die außerdem noch als
volatile deklariert werden, also z.B. so:
1
volatileinta;
Sonst kommt in 4 Wochen ein Posting daß angeblich der Compiler defekt
wäre.
Edit:
Und wenn sie breiter ist als das was der Prozessor in einer einzigen
Instruktion lesen oder schreiben kann (also bei AVR wäre das alles was
breiter ist als ein Byte) dann muß außerdem noch auf atomaren Zugriff
geachtet werden: Interrupts sperren während die main darauf zugreift.
Die Anfrage ist ziemlich unklar formuliert. Ich verstehe sie so:
Er hat in der Datei main.c eine globale Variable. In der Datei
interrupt.c möchte er auf sie zugreifen.
Die einfachste Möglichkeit besteht IMHO darin, sie in der interrupt.c
erneu zu deklarieren, aber mit dem Schlüsselwort "extern" davor. Also:
extern int i;
Bei Interrupts sollte man noch bedenken, was wohl passieren könnte, wenn
das laufende Programm während des Zugriffs durch den Interrupt
unterbrochen wird und dieser dann den Inhalt der Variable verändert.
Hier lohnt es sich, mal nach den Stichworten "volatile", "atomarer
zugriff" und "interrupts sperren". Bei AVR auch "cli()" und "sei()".
Volatile ist unter Umständen auch ohne Interrupts nötig, sofern mehrere
*.c Dateien schreibend auf die Variable zugreifen und sich dabei
gegenseitig stören.
Mal angenommen, du hast in der main.c die Funktion verdopple_i() und in
der interrupt.c steht irgendwo so etwas:
1
while(i<100)
2
{
3
verdopple_i();
4
}
Dann brauchst du volatile. Denn ohne das volatile Schlüsselwort würde
der vom Compiler erzeugte Maschinencode den Wert der Variable i in ein
CPU Register kopieren, und dann mit 100 vergleichen. Da er nicht damit
rechnet, dass i durch die Funktion verdopple_i() verändert wird, würde
er beim nächsten Schleifendurchlauf nicht den aktuellen Wert von i
prüfen, sondern die nun veraltete Kopie im Register.
"damit rechnen", dass eine Variable veränder wird, tut der Compiler nur
bei Funktionen, die in der selben *.c Datei stehen. Mit dem
Schlüsselwort "volatile" kopiert er i immer wieder neu in ein Register,
bevor er mit 100 vergleicht. Das kostet Performance.
volatile extern int i;
Noch ein Tipp: Nenne die Variable nicht i, das provoziert
Namenskonflikte. Vorschlag: main_global_pulse_counter
Stefanus F. schrieb:> "damit rechnen", dass eine Variable veränder wird, tut der Compiler nur> bei Funktionen, die in der selben *.c Datei stehen. Mit dem> Schlüsselwort "volatile" kopiert er i immer wieder neu in ein Register,> bevor er mit 100 vergleicht. Das kostet Performance.
würde er das nicht tun, müsste ich alle Variablen auch volatile in
main.c deklarieren, richtig?
> volatile extern int i;>> Noch ein Tipp: Nenne die Variable nicht i, das provoziert> Namenskonflikte. Vorschlag: main_global_pulse_counter
danke allen für die Unterstützung
Stefanus F. schrieb:> "damit rechnen", dass eine Variable veränder wird, tut der Compiler nur> bei Funktionen, die in der selben *.c Datei stehen.
Gibt es dafür einen Beleg? Wenn ich eine unbekannte Funktion aufrufe,
ist doch jede globale Variable potentiell geändert.
Im Gegenteil: nur wenn sie in gleicher C-datei ist, kann der Compiler
sehen, ob sie unverändert ist..
sepp schrieb:> Ich habe eine weitere Frage.> Ich habe ein struct in commands.h erstellt.typedef struct scharfeFrauen{> uint8_t blond;> uint8_t brünett;> }scharfeFrauen_t;> und Konstanten definiert#define scharfeGeschoss (scharfeFrauen_t)> {0x00, 0x01}> #define scharfeGeschoss2 (scharfeFrauen_t) {0x02, 0x03}> und Array, den ich global nutzen muss, im selben Dokument commands.h> erstellt und in main.c eingebunden:static const uint8_t array[] => {scharfeGeschoss.blond, scharfeGeschoss2.blond};> jetzt meckert mir der Compiler troztdem, dass ich den array als const> definieren muss.> Warum? Das ist er ja bereits.Thomas E. schrieb:> sepp schrieb:>> scharfeFrauen>> sepp schrieb:>> scharfeGeschoss.blond>> Solche politisch unkorrekten Ausdrücke sind bei gesitteten Compilern> nicht erlaubt.
ok, beachte ich das nächste Mal.
An der Antwort wäre ich aber trotzdem interessiert.
Auch wenn die Brünette schärfer ist als die Blonde:
Der Compiler wird sie wegen des Umlautes verschmähen.
Sieht man gleich daran, dass er rot wird.
Oder akzeptieren moderne Compiler inzwischen UTF?
Ich verstehe nicht so ganz
scharfeGeschoss ist vom Typ scharfeFrauen_t
Mit scharfeGeschoss.blond greife ich doch auf das 1. Element vom typedef
struct
Wenn ich das mit einem Array in der main direkt mache, funktioniert das
doch auch.. und ich kann auf die Elemente so zugreifen und übergeben.
Also versteht das doch der Compiler doch?
Ich wüsste sonst nicht warum das funktioniert.
zyxw schrieb:> Auch wenn die Brünette schärfer ist als die Blonde:> Der Compiler wird sie wegen des Umlautes verschmähen.> Sieht man gleich daran, dass er rot wird.> Oder akzeptieren moderne Compiler inzwischen UTF?
edit
habe ich nur hier falsch drin
ein #define ist aber kein Zugriff, sondern nichts anderes als eine
Textersetzung.
Darum steht für den Compiler da:
Rufus Τ. F. schrieb:> static const uint8_t array[] = {(scharfeFrauen_t) {0x00, 0x01}.blond,> (scharfeFrauen_t) {0x00, 0x01}.blond};
Folgendes gillt nur für Globale Definitionen.
In C++ gäbe es constexpr, aber in c nicht. Der Wert der Variable ist
erst nach dem Linken zur Runtime bekannt, aber nicht zur Compiler time.
Man hätte in Standard theoretisch bei static const eine Ausnahme machen
können, hat man aber nicht. Ausdrücke wie:
1
staticconstinta=1;
2
staticconstintb=a;
sind deshalb nicht möglich. Es spielt dabei keine Rolle, ob man explizit
b global Deklariert, oder implizit als Compound Literal anlegt. Bei
Integern kann man immerhin noch auf enums zurück greifen, die sind echte
Konstanten:
1
enum{
2
a=1
3
};
4
5
enum{
6
b=a
7
};
8
9
constc=b;
Man kann jedoch Variablen Referenzieren:
1
inta=1;
2
int*b=&a;
3
int*c=&(int){5};
4
int*d=(int[]){6};
Du könntest mit Macros auch sowas machen:
1
#define ZAHLEN \
2
X(1,2) \
3
X(2,3)
4
5
#define X(A,B) A,
6
intc[]={ZAHLEN};
7
#undef X
8
9
intmain(){(void)c;}
Auch mit Funktionen mit "__attribute__((constructor,used))" kann man
einige Schweinereien anstellen. Ich verwende die gerne mit einem Macro
für globale linked lists.
@Achim S.
> Gibt es dafür einen Beleg?
Ich hasse diese Fragen. Welche Art von beleg würdest du denn
akzeptieren? Ein Buch von mir? Ein Buch von Peter? Ein Video bei
Youtube?
Ich habe das irgendwo gelesen, ausprobiert und für korrekt befunden. Das
genügt mir. Wo ich die Weisheit her habe und wann und wie ich es
überprüft habe, ist für mich unwichtig und daher vergessen.
Niemand zwingt Dich, mir zu glauben. Also lass es einfach bleiben, mir
ist egal ob du gegen die nächste Wand läufst.
Also wie kann ich das dann machen, dass ich die Werte schön von einem
anderen h-file aus per Hand zuerst definieren kann und diesem im Array
übernommen werden, wenn ich nicht jedes Mal den Code durchgehen möchte
und es passend ändere?
sepp schrieb:> Also wie kann ich das dann machen, dass ich die Werte schön von einem> anderen h-file aus per Hand zuerst definieren kann und diesem im Array> übernommen werden, wenn ich nicht jedes Mal den Code durchgehen möchte> und es passend ändere?
Das hängt immer ganz von der Datenstruktur ab, die du definieren willst.
Die Daten selbst würde aber auch in ein .c File legen. Wozu willst du
eigentlich überhaupt das struct "scharfeFrauen" wenn du es sowieso nicht
verwendest, um darin die Werte zu organisieren? Bzw. warum nicht einfach
ein Array von "scharfeFrauen" erstellen, wozu die Arrays? Das erscheint
mir redundant. Und spielt Speicherverbrauch oder Performance auch eine
Rolle? Sonst könnte man die Arrays auch zur Laufzeit Alloziieren.
Oh, und bei meiner Variante mit dem "#define ZAHLEN" kannst du
unterschiedliche Werte unterschiedlich expandieren, jenachdem, wie du X
definierst:
1
#define X(A,B) A,
2
intalle_werte_a[]={ZAHLEN};
3
#undef X
4
5
#define X(A,B) B,
6
intalle_werte_b[]={ZAHLEN};
7
#undef X
Genügt das nicht?
Im Header ist dass ja dann einfach nur: