mikrocontroller.net

Forum: Compiler & IDEs Benötige Nachhilfe in C - Call by Referenz


Autor: Holger Gerwenat (holli1195)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Morgen Alle zusammen!

ich hätte da ein paar "Urschleimfragen" zu C und AVR-GCC.

1. kann mir jemand sagen, warum die letzte Version vom AVR-GCC immer die 
Funktion
void main(void);
anmeckert und einen int Rückgabewert haben möchte?

Ich habe mir, als ich mit C und Atmel angefangen habe, mal eingeprägt, 
daß ein Mikrocontrollerprogramm nichts zurückgeben kann. Wohin auch? 
Sowas wie z.B. ein Bios ist ja nicht da und da die Verarbeitung ja meist 
in einer Endlosschleife endet, wird ja ein return (x) auch nie erreicht. 
Bisher scheint das gestimmt zu haben, jetzt bekomme ich immer eine 
Warnung.

2. eine Funktion gibt 2 Strings zurück. Unter
http://abraham.informatik.fh-lausitz.de/profs/robe...
habe ich eine prima Erklärung zu Call by Referenz gefunden...
Dann hab ich es so probiert:

in meine.c:
void Funktion(char *String1, char *String2); //Deklaration einer 
Funktion
                                             //Rückgabe 2x Zeiger auf 
Str

void Funktion(char *String1, char *String2)
{
...
*String1="ist";    //zum Test einfach was zuweisen
*String2="egal";
}

in main.c:

#include meine.c

char[5] Ausgabe1;  //String anlegen mit platz für 'i s t \ 0'
char[6] Ausgabe2;

void main(void)
{
Funktion(&Ausgabe1,&Ausgabe2);
putLCD(Ausgabe1);
...
}

geht so aber nicht...
Im Buch "C für Mikrocontroller" Seite 233 sind Datentypen aufgeführt. 
Danach ist char[] ein Zeiger auf ein String (Str).

Hab ich's also so probiert:
void Funktion(char []String1, char []String2);

geht auch nicht...

Heute Nacht fiel mir ein, geht das überhaupt? C kennt ja den Datentyp 
"String" gar nicht. Geht der Datenaustausch da evt. nur direkt über eine 
globale Variable?

Schon mal vielen Dank, daß es mir einer erklärt...

Gruß Holger

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Holger Gerwenat wrote:
> Guten Morgen Alle zusammen!
>
> ich hätte da ein paar "Urschleimfragen" zu C und AVR-GCC.
>
> 1. kann mir jemand sagen, warum die letzte Version vom AVR-GCC immer die
> Funktion
> void main(void);
> anmeckert und einen int Rückgabewert haben möchte?

Weil C seit Anbeginn der Welt von main() fordert, dass es einen
int zurückgeben muss.
Es waren lediglich einige Compiler (speziell die Micorosoft
Compiler) die anfingen void main() zu akzeptieren. Vorgesehen
war das nie. Und irgendwann haben sich die Macher von gcc
entschlossen, dies zu einer Fehlermeldung zu machen um die
abtrünnigen Programmierer wieder auf den Pfad der Tugend
zurückzuführen.

> Ich habe mir, als ich mit C und Atmel angefangen habe, mal eingeprägt,
> daß ein Mikrocontrollerprogramm nichts zurückgeben kann. Wohin auch?

Spielt keine Rolle.
Der Returntyp von main() ist int. Punkt.
Steht so in der Sprachdefinition.

> 2. eine Funktion gibt 2 Strings zurück. Unter
> http://abraham.informatik.fh-lausitz.de/profs/robe...
> habe ich eine prima Erklärung zu Call by Referenz gefunden...
> Dann hab ich es so probiert:
>
> in meine.c:
> void Funktion(char *String1, char *String2); //Deklaration einer
> Funktion
>                                              //Rückgabe 2x Zeiger auf
> Str
>
> void Funktion(char *String1, char *String2)
> {
> ...
> *String1="ist";    //zum Test einfach was zuweisen
> *String2="egal";
> }
>
> in main.c:
>
> #include meine.c
>
> char[5] Ausgabe1;  //String anlegen mit platz für 'i s t \ 0'
> char[6] Ausgabe2;
>
> void main(void)
> {
> Funktion(&Ausgabe1,&Ausgabe2);
> putLCD(Ausgabe1);
> ...
> }
>
> geht so aber nicht...

Logisch.
Strings kann man in C nicht zuweisen. Deine Zuweisung da oben
macht ganz was anderes. Die Pointervariable, die die Funktion
erhält (in C gibt es nämlich in Wirklichkeit keinen Call
by Referenz, alles wird immer per Value übergeben) wird
auf die Startadresse deiner konstanten Strings gesetzt.
Das hilft dir aber nicht viel, weil diese Poitnervariable
ja nur während der Laufzeit der Funktion existiert und
nach Beendigung der FUnktion wieder zerstört wird.
Was du erreichen willst, geht so

void Funktion(char *String1, char *String2)
{

  strcpy( String1, "ist" );    //zum Test einfach was zuweisen
  strcpy( String2, "egal" );
}

int main(void)
{
  Funktion( Ausgabe1, Ausgabe2 );
  putLCD(Ausgabe1);
  ...
}

Beachte auch, dass die & im Aufruf unsinnig sind. Arrays werden
sowieso immer an Funktionen übergeben, indem die Adresse des
ersten Elements übergeben wird.
Leider akzeptieren viele Compiler die Schreibweise &Array an dieser
Stelle als Ersatz für die korrekte Schreibweise ohne &

> Hab ich's also so probiert:
> void Funktion(char []String1, char []String2);
>
> geht auch nicht...

Ist auch klar. Das ist nur eine andere Schreibweise für
einen Pointer. Meine persönliche Meinung: vergiss diese
Notation wieder. Sie bringt nur Konfusion.

Man könnte es in deinem speziellen Fall auch so machen

void Funktion(const char **String1, const char **String2)
{
 *String1="ist";    //zum Test einfach was zuweisen
 *String2="egal";
}

int main()
{
  const char* pStr1, const char* pStr2;

  Funktion( &pStr1, &pStr2);
  putLCD( pStr1 );
}

Dann ist allerdings die Funktion dafür verantwortlich, den
Speicher zur Verfügung zu stellen, in dem die tatsächlichen
Character gespeichert sind. Dieser Speicher muss auch nach
Beendigung der Funktion noch existieren! Im Regelfall geht
dies nur wenn
* der String, so wie in deinem Fall, ein String-Literal ist
* der String in einem globalen Array residiert
* mit malloc() und free() gearbeitet wird.

> Heute Nacht fiel mir ein, geht das überhaupt? C kennt ja den Datentyp
> "String" gar nicht. Geht der Datenaustausch da evt. nur direkt über eine
> globale Variable?

http://www.mikrocontroller.net//articles/FAQ#Wie_f...

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Holger Gerwenat wrote:
> Guten Morgen Alle zusammen!
>
> ich hätte da ein paar "Urschleimfragen" zu C und AVR-GCC.
>
> 1. kann mir jemand sagen, warum die letzte Version vom AVR-GCC immer die
> Funktion
> void main(void);
> anmeckert und einen int Rückgabewert haben möchte?
In ANSI-C ist main() nunmal vom Typ int, und der GCC-C-Compiler ist ein 
ANSI-Compiler und meckert deshalb zu Recht. Das war auch bei bisherigen 
GCC-Versionen nicht anders.

> Ich habe mir, als ich mit C und Atmel angefangen habe, mal eingeprägt,
> daß ein Mikrocontrollerprogramm nichts zurückgeben kann. Wohin auch?
> Sowas wie z.B. ein Bios ist ja nicht da und da die Verarbeitung ja meist
> in einer Endlosschleife endet, wird ja ein return (x) auch nie erreicht.
> Bisher scheint das gestimmt zu haben, jetzt bekomme ich immer eine
> Warnung.
Es gibt kommerzielle Compiler, die tatsächlich void als Typ für main 
akzeptieren, was dann aber nicht mehr durch den ANSI-Standard abgedeckt 
ist. Es ist aber auch keine Fehlermeldung, sondern nur eine Warnung, 
die Dich darauf hinweisen soll, dass da etwas steht, was evtl. anders 
gemeint sein könnte...

> #include meine.c
Da fehlt was, außerdem sollte man keine C-Dateien direkt includen.

> char[5] Ausgabe1;  //String anlegen mit platz für 'i s t \ 0'
Der Nullterminator '\0' ist ein Zeichen...

> char[6] Ausgabe2;
>
> void main(void)
> {
> Funktion(&Ausgabe1,&Ausgabe2);
Die '&' sind falsch. Bei Arrays gilt: Der Name des Arrays repräsentiert 
die Adresse des ersten Array-Elements (array = &array[0]). Du versuchst, 
die Adresse der Adresse des ersten Elements zu übergeben, und das geht 
schief. Lass die Adress-Operatoren weg.

> Heute Nacht fiel mir ein, geht das überhaupt? C kennt ja den Datentyp
> "String" gar nicht. Geht der Datenaustausch da evt. nur direkt über eine
> globale Variable?
Nein, C kennt keinen Datentyp "string". Aber mit Arrays funktioniert es 
auch, wenn man die Elemente einzeln verarbeitet oder Funktionen wie 
strncpy() aus der string.h verwendet.

Autor: Holger Gerwenat (holli1195)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Karl-Heinz, Danke Johannes!

Ich hab ja meine Frage kaum getippt.....schon Antwort da. Wie geht das? 
:-)))

Gut, ne Menge gelernt:

1. Main ist ab jetzt immer ein int!
2. Klar, #include *.c hab ich nur der Einfachheit halber geschrieben,
   in Wirklichkeit wird natürlich korrekt eine *.h eingebunden ;-)
3. Oh! \0 ist ein Zeichen -> nicht gewußt -> gemerkt
4. Meine Aufgabe werde ich so wie beschrieben lösen...

Nochmals Danke, für Eure Hilfe.

Gruß Holger

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Holger Gerwenat wrote:

> 3. Oh! \0 ist ein Zeichen -> nicht gewußt -> gemerkt

Wenn ein Zeichen mit \ beginnt, dann gehört immer noch ein
zweites Zeichen dazu. \ ist das Fluchtsymbol, welches dem
Compiler sagt, dass das nächste Quellcode-Zeichen anders zu
interpretieren ist

   \n     ist ein Line Feed
   \r     ist ein Carriage Return
   \f     ist ein Form Feed (neue Seite am Drucker)
   \t     ist ein Tabulator
   \b     ist ein Backspace
   \a     ist das Bell-Symbol (die Glocke. Hat heute keine
              Bedeutung mehr und kommt noch aus der Zeit als
              Terminals noch auf Papier schrieben und nicht auf
              einem Monitor. Manche Terminals beepen noch, wenn sie
              dieses Zeichen empfangen)
   \"     ist ein " Zeichen in einem String
   \0     ist der Null-Terminator eines Strings
   \\     ist dann letztendlich ein einzelner \


Aber: Auch wenn du 2 Tastendrücke dafür brauchst, aus Sicht des
Compiler ist das immer ein einzelnes Zeichen.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:
> Fluchtsymbol

Würg! Ist das jetzt die 1:1 Übersetzung von Escape-Character oder gibt's 
das so wirklich auf deutsch? ;)

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon K. wrote:
> Würg! Ist das jetzt die 1:1 Übersetzung von Escape-Character oder gibt's
> das so wirklich auf deutsch? ;)
Also ich find die Übersetzung klasse...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon K. wrote:
> Karl heinz Buchegger wrote:
>> Fluchtsymbol
>
> Würg! Ist das jetzt die 1:1 Übersetzung von Escape-Character oder gibt's
> das so wirklich auf deutsch? ;)

Ich hatte schon die Finger über Escape. Hab aber dann schnell
umdirigiert um eine Verwechslung mit dem Escape-Character 0x1B
zu vermeiden.

Ich glaube den Terminus Fluchtsymbol tatsächlich das erste
mal in einer deutschen Version von K&R gelesen zuhaben :-)

Ansonsten: ja natürlich - Würg auch hier bei mir.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den Begriff (auch "Fluchtzeichen") habe ich schon öfters gehört. Das ist 
tatsächlich die gängigste Übersetzung. Sie zeigt, daß manche Begriffe 
besser unübersetzt bleiben.

Autor: Michael Glunz (glunzl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Fluchtsequenz" wurde in Modemhandbüchern gerne genutzt (V42.bis als 
Bsp). Nein kein DSL-Modem-Handbuch ;-)

Gruß
Michael

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.