morsche,
ich kapiers nicht ! Ich habe 2 .C Files.
In dem einen habe ich meine main() Funktion und die Deklaration einer
Struct , alla :
1
File1.c:
2
3
typedefstruct{unsignedcharDaten[10];}Data;
4
5
6
intmain(void){
7
....
8
DatamyData;
9
machwas(&myData);// übergibt doch Referenz auf Data oder nicht ?
10
....
11
}
12
13
14
File2.c:
15
16
voidmachwas(Data*daten){
17
daten[1]=100;
18
19
return*daten;
20
}
da fängts schon direkt an,dass er Data nicht kennt, ok wird ja nur im
File1 deklariert. Ich kann jetzt zwar die Deklaration im File2 noch
einmal machen, macht aber doch keinen Sinn oder ?
Ich will "nur" eine definierte Struct an eine Funktion übergeben, füllen
lassen und wieder zurück damit. Sollte eigentlich nicht so schwer
sein...
gruß
Oddel
Zwei Fehler in drei Zeilen Code.
Du kannst keinen Wert zurückgeben, wenn Du die Funktion als void
deklarierst
Wenn Du einen Pointer auf eine Struct übergibst, musst Du den Pointer
natürlich auch dereferenzieren:
Du hast den Zugriff auf Elemente eines Structs nicht verstanden.
Außerdem deklarierst du deine Funktion mit dem Rückgabewert void, hast
aber ein return drinne? Auch falsch.
Dein Aufruf müsste wie folgt aussehen
1
File2.c:
2
3
voidmachwas(Data*daten){
4
daten->Daten[1]=100;
5
}
Um es dir vl. etwas verständlicher zu amchen mal eine etwas klarere
Namensgebung
Was für einen Sinn soll eine Struktur mit nur einem Element haben?
Sicher musst du die Variable auch in der zweiten c-Datei deklarieren -
und zwar als "extern".
Außerdem brauchst du auch kein typedef in deinem c-File.
1
structblabla_typ
2
{
3
unsignedshortvara;
4
intvarb,varc;
5
};
6
[c]
7
danneinmal:
8
[c]structblabla_typblabla_tag;
und alle anderen male:
1
externstructblabla_typblabla_tag;
benutzung:
1
voidfoobar()
2
{
3
blabla_tag.vara=1337;
4
blabla_tag.varb=-128;
5
}
Vorsicht falls du bei der Deklaration auch gleich initialisiert:
Initialisierung bei der externen Deklaration weglassen!
Oddel schrieb:> Ich kann jetzt zwar die Deklaration im File2 noch> einmal machen, macht aber doch keinen Sinn oder ?
Doch. Genauso geht es, und nur so. Um sich die Tipparbeit zu ersparen,
schreibt man die Deklaration daher üblicheriwese in ein headerfile,
welches dann von allen .c-Dateien, die dieses Struct benutzen,
inkludiert wird.
Oliver
Oddel schrieb:> ok wird ja nur im> File1 deklariert. Ich kann jetzt zwar die Deklaration im File2 noch> einmal machen, macht aber doch keinen Sinn oder ?
Dafür gibt es header files mit Endung .h. Die bindest du mit #include in
beide c files ein.
struct macht so verwendet keinen Sinn. Ist das zum üben, oder kommen
weitere Daten hinzu?
upps, das ging ja schnell. Danke !
ok das mit dem void da gehört mir eins hinter die Ohren.
Grundsätzlich wollte ich ein Array als Rückgabewert einer Funktion und
habe dann im Galileo online book, den Umweg über die Struct gefunden.
Hat aber nicht funktioniert und jetzt habe ich soviel probiert.....
Wie macht ihr die Rückgabe eines Arrays ?
Oddel schrieb:> Grundsätzlich wollte ich ein Array als Rückgabewert einer Funktion
Warum? Da du die Referenz auf das Array übergibst (den Zeiger), kannst
du in dem Array doch eh alles ändern was du willst.
Kauf dir ein anderes Buch (von einem anderem Autor).
Oddel schrieb:> habe dann im Galileo online book, den Umweg über die Struct gefunden.
Übler Mist, der nicht andres macht, als die Optimierung herauszufordern.
Den Zeiger kriegst du bei deinem Array eh frei Haus - der optimale
Übergabewert.
@ Oddel
>... habe dann im Galileo online book, den Umweg über die Struct gefunden.
Möglicherweise lohnt es sich, wenn Du uns mal den Link auf die
HTML-Seite in der Online-Version gibst, auf der steht, das man Daten
innerhalb einer struct an eine Funktion übergibt, um sie dauerhaft
manipulieren zu können.
Ich vermute, dass es sich um ein Missverständnis handelt, das man mit
Gewinn für Dich aufklären könnte. Oder es handelt sich um einen echten
Fehler in dem Buch, worüber man den Verlag aufklären könnte.
Es ist wohlgemerkt nicht unmöglich das so zu tun aber völlig unnötig.
ah ok,
das bedeutet , das hier wäre absolut korrekt, ich übergebe die Referenz
data , fülle die Speicheradresse mit Daten und das war's keine Rückgabe
nix, da der Speicher direkt verändert wird.
[c]
int main(void){
unsigned char data[10];
machwas(&data);
....
}
file2.c
void machwas(unsigned char *daten){
int i =0;
for(i=0;i<= Packetlen ;i++){
daten[i]=holeDaten();
}
}
ok, wenn jetzt daten[], Datenpakete enthält mit 10 Byte länge und ich
die Anforderung zum füllen der daten[] über einen Interrupt bekomme,
würde es doch Sinn machen aus diesem Array ein 2 Dimensionales Array zu
machen oder ein Struct - Array ?
Bsp.:
INT -> hole Datenbyte 1...10 und schreibe in Array daten !
mitten in der Verarbeitung von diesem Array kommt erneut ein
INT -> hole Datenbyte 1...10 und schreibe in nächstes Array daten !
usw.
Gruß
Oddel
P.S.: Tolles Forum !
Oddel schrieb:> machwas(&data);
ist so nicht richtig.
entweder
machwas(&data[0]);
oder besser
1
machwas(data);
Da machwas() aber nicht weiß und auch nicht raus finden kann wie groß
der Platz in data ist, solltest du ihn mit übergeben.
Bedenke das bei dir das Element data[10] nicht existiert.
Auch ist es in C üblich einen Funktionswert zurück zu geben. Sei es als
Fehlererkennung oder zur Weiterverarbeitung. Du musst ihn ja nicht
beachten.
Hier mal ein Stück code von mir, in dem genau sowas gemacht wird.
uarx[] ist global und enthält empfangene Daten.
*command ist ein pointer auf ein array. Aufgerufen wird das so:
1
if(chk_for_cmd("set-blabla"))do_blabla();
1
unsignedcharchk_for_cmd(constchar*command)
2
{/* !WILDCARD character! == '#' will be passed to uarx_param */
3
volatileunsignedchar*uarxp=&uarx[0];
4
5
if(uarx_done)
6
{/* uart rx done - process receivings */
7
while(*uarxp==*command)
8
{/* if current characters are identical, *
9
* increase to check next character */
10
uarxp++;
11
command++;
12
if(*command=='#')
13
{/* wildcard character for numbers */
14
uarx_param=*uarxp;
15
uarxp++;
16
command++;
17
}
18
if(*command=='\0')
19
{/* next character to compare matches string-end *
20
* -> whole command-string detected -> return 1 */
21
uarx_done=0;
22
uarx_clr();
23
return1;
24
}
25
}
26
}
27
/* no return 1 -> command not detected -> return 0 */
28
return0;
29
}
Die Variante mit dem lokalen array verbraucht nur mehr Speicher, weil er
einmal im Unterprogramm und einmal beim Aufrufenden belegt werden muss.
Hallo DirkB,
Danke für Dein Beispiel hat funktioniert ! Endlich mal wieder Licht am
Ende des Tunnels :)
Aber eine Frage habe ich noch:
ich rufe die Funktion
1
machwas(daten);
2
3
unsignedchar*machwas(unsignedchar*daten,intanz){
4
inti=0;
5
for(i=0;i<anz;i++){
6
daten[i]=holeDaten();
7
}
8
returndaten
9
}
auf. Diese hat doch ein Return-Statement , wieso bringt mir der Compiler
einen Fehler wenn ich aus machwas(daten); -> Dummy=machwas(daten)
mache ?
gruß
Oddel
Dummy von unsigned char:
main.c|200|error: void value not ignored as it ought to be|
kann ich ein Array das ich mit &data übergebe und in der Funktion mit
*data verarbeite an eine weitere Funktion mit data übergeben ?
Also von main -> Func1 und dann -> Func2 ?
Und kann ich mit
Arrsize = (Data,sizeof(Data) / sizeof(Data[0]))
die Anzahl Elemente ermitteln ?
und wofür genau steht * am Funktionsnamen in Deinem Beispiel ?
Danke , ich glaub das waren genug Fragen für heute.....
Oddel schrieb:> und wofür genau steht * am Funktionsnamen in Deinem Beispiel ?
Das besagt, das die Funktion einen Zeiger zurückgibt. Genauer einen Wert
vom Typ (unsigned char *).
Die Anzahl der Elemente geht mit
1
Arrsize=(sizeof(Data)/sizeof(Data[0]))
ACHTUNG. Das geht aber nur da, wo das Array auch bekannt ist.
In der Funktion machwas() geht das nicht mehr.
Und klar kannst du die Daten weiterreichen.
Zu der Fehlermeldug: Irgendwo hast du machwas noch mit void als
Rückgabewert definiert.
Hallo Dirk,
vielen Dank für Deine Hilfe. Bis jetzt macht mein Programm gute
Fortschritte.
Wie kann ich ein Array zur Manipulation an einen Interrupt übergeben
bzw.
von einem Interrupt auf die Speicherstelle zugreifen ?
Ich deklariere das Array im File1.c und verarbeite den Interrupt in
File2.c....
gruß