www.mikrocontroller.net

Forum: GCC *Pointer und struct, Anfängerfrage


Important announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Simon (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
SYNOPSIS
int modbus_write_and_read_registers
(modbus_t *ctx, int write_addr, int write_nb, const uint16_t *src, int read_addr, int read_nb, const uint16_t *dest);

"You must take care to allocate enough memory to store the results in 
dest (at least nb * sizeof(uint16_t))."


const uint16_t *dest

1) Wieso wird hier const verwendet?
2) uint16_t *dest

bedeutet das jedesmal wen ich ein dest++ mache er den Pointer um 16 bits 
bewegt?

Autor: adf (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Simon schrieb:
> bedeutet das jedesmal wen ich ein dest++ mache er den Pointer um 16 bits
> bewegt?

??? dest++ inkrementiert den Pointer, da wird gar nicht bewegt.

Autor: Simon (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
adf schrieb:
> ??? dest++ inkrementiert den Pointer, da wird gar nicht bewegt.

um 16 Bit?

Was wäre anders wenn es so heiszen würde:
const uint8_t *dest)

Autor: Oliver (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert

Autor: Simon (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Danke, bin noch am lesen, garnicht schlecht.

Autor: Simon (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Ich checks immer noch nicht, warum const?

const sagt aus das die Variable einmal deklariert und zugewiesen wird, 
danach nicht mehr geändert.

Bedeutet das nun das ich die Variable innerhalb der funktion nicht vor 
habe zu verändern?
void funktion (const uint16_t *dest);

der Aufruf wäre dann mit
funktion(*variable); ?

Und was sagt mir uint16_t in dem Zusammenhang? das der Pointer aus einer 
16 Bit addresse besteht?

Autor: DirkB (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Simon schrieb:
> der Aufruf wäre dann mitfunktion(*variable); ?
Nein

mitfunktion(&variable);

Die Funktion erwartet eine Adresse und die bekommst du mit dem 
Adressoperator &

> Und was sagt mir uint16_t in dem Zusammenhang?
Das an der Adresse auf die der Zeiger zeigt eine vorzeichenlose 16-Bit 
Ganzzahl steht.

Der Compiler muss wissen wie er die Daten an der Adresse interpretieren 
soll.

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

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Simon schrieb:
> Ich checks immer noch nicht, warum const?

Gute Frage

> const sagt aus das die Variable einmal deklariert und zugewiesen wird,
> danach nicht mehr geändert.

An dieser Stelle sagt das const aus, dass die aufgerufene Funktion den 
Pointer nicht benutzen wird um über diesen Pointer die Werte an der 
Stelle im Speicher zu verändern, auf die der Pointer zeigt.

Beispiel

void foo( uint16_t * pDest )
{
  *pDest = 5;
}

int main()
{
  uint16_t i;

  foo( &i );
}

ich übergebe der Funktion die Adresse von i. Die Funktion benutzt diese 
Adresse, um über diese Adresse die Variable i zu verändern.

Und jetzt das ganze const

void foo( const uint16_t * pDest )
{
  *pDest = 5;
}

int main()
{
  uint16_t i;

  foo( &i );
}

jetzt gibt mir die Funktion die Zusicherung, genau das nicht zu tun. Sie 
wird die Adresse, die ich ihr gebe, nicht dazu benutzen um die Variable 
zu verändern.
Wenn du das compilierst, dann wird es einen Fehler hier
  *pDest = 5;
geben. Denn diese Operation versucht genau das, was durch das const in 
der Argumentliste ausgeschlossen wurde. Der Compiler verhindert das 
daher.

Allerdings:
Ich weiß zwar nicht, was deine Funktion genau macht. Aber wenn ich raten 
müsste, würde ich den Argumentnamen 'dest' alsw Kurzform für Destination 
ansehen, also das Ziel einer Operation. Und da würde ich mal raten, dass 
dieses Ziel irgendwie verändert wird. Wodurch das const keinen Sinn 
ergibt.
Aber: Das ist jetzt nur geraten. Genaueres kann man nur sagen, wenn man 
weiß was das für eine Funktion ist und welchen Zweck sie hat.

Autor: Oliver (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Karl Heinz Buchegger schrieb:
> Und da würde ich mal raten, dass
> dieses Ziel irgendwie verändert wird. Wodurch das const keinen Sinn
> ergibt.

Da brauchst du nicht zu raten, das steht sogar da:

Simon schrieb:
> "You must take care to allocate enough memory to store the results in
> dest (at least nb * sizeof(uint16_t))."

Da hat der unbekannte Autor der Funktion das mit dem const auch nicht 
auf die Reihe gekriegt. Im Sourcecode wurde die aber wohl nicht 
ausgeliefert, denn jeder "anständige" C-Compipler würde sich weigern, 
den Schreibzugriff in das Feld zu übersetzen.

Oliver

Autor: Decius (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Egal ob du eine Variable als uint16_t oder uint8_t vereinbarst, haben 
Pointer eine konstante Größe. Sie beinhalten doch nur die Adresse auf 
eine Speicherstelle. Der Datentyp definiert nur wie die Daten an dieser 
Speicherstelle zu interpretieren sind.

Wie ein Pointer auf dekrementieren oder inkrementieren reagiert kann 
ohne Bezug zu einem realen System nicht definiert werden. Auf der Intel 
Plattform ist eine Byteweise Addressierung üblich. Das heißt, ++ und -- 
verändern die Pointeradresse um ein Byte, egal um welchen Datentyp es 
sich handelt.

Autor: Joachim Drechsel (Firma: JDCC) (scheppertreiber)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Decius schrieb:
> Das heißt, ++ und --
> verändern die Pointeradresse um ein Byte, egal um welchen Datentyp es
> sich handelt.

Nein. Da heißt es aufpassen.

Autor: Decius (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
habe ja geschrieben, das das Systemabhängig ist.

Autor: Decius (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Ok, hinsichtlich ++ und -- bin ich jertzt doch etwas unsicher. :-)

Hsabe auch sowas gelesen, daß das Ergebnis in diesen Fällen doch vom 
Datentyp abhängig ist. Also wenn du ein Array von short hast, verändert 
die Adresse sich um 2Byte.

Aber Systemabhängig muß das ganze aber auch sein. Denn die Byteweiyse 
Addressierung der intelplattform ist bei ARM's nicht üblich.

Autor: Oliver (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Decius schrieb:
> Wie ein Pointer auf dekrementieren oder inkrementieren reagiert kann
> ohne Bezug zu einem realen System nicht definiert werden.

Natürlich kann das vollständig definiert werden, und das ist es auch. 
Kurz gesagt, zeigt der pointer nach der Inkremetierung auf das folgende 
Element gleichen Typs. So einfach ist das. Wie die Bytes im Speicher 
angeordnet sind, ist zwar implementationsabhängig, abder der Spache C 
völlig egal.

Oliver

Autor: Decius (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
ok, hast recht. Ist wieder gerade gerückt. :-)

Autor: Dosmo (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Simon schrieb:
> Ich checks immer noch nicht, warum const?
>
> const sagt aus das die Variable einmal deklariert und zugewiesen wird,
> danach nicht mehr geändert.
>
>
> Bedeutet das nun das ich die Variable innerhalb der funktion nicht vor
> habe zu verändern?
const int a;
 ist eine Konstante.
const int *a;
 ist ein (variabler) Zeiger auf eine Konstante.
Der Zeiger selber ist dann keine Konstante!

Stell Dir vor, Du hast eine Tabelle aus Konstanten und Du willst mit 
einem Zeiger durch diese Tabelle gehen. Dann muß der Zeiger veränderbar 
sein, neech?
int * const a;
 wäre ein konstanter Zeiger auf eine Variable.
const int * const a;
 wäre ein konstanter Zeiger auf eine Konstante.

Es gibt tatsächlich Anwendungsfälle für alle Varianten.

Autor: Klaus Wachtler (mfgkw)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Dosmo schrieb:
> const int a; ist eine Konstante.const int *a; ist ein (variabler) Zeiger auf 
eine Konstante.

Jein.
Genau genommen ist es eine Variable und mit dem const sagt man, daß man 
im Geltungsbereich dieser Deklaration diese Variable nicht ändern 
möchte.

Der Unterschied ist z.B. dann relevant, wenn man Parameterdeklarationen 
hat:
void f1( int * p_i )
{
   *p_i++;
   // ...
}

void f2( const int * p_i )
{
   // jetzt nicht mehr möglich: *p_i++;
   // ...
}

...
   int          i = 0;
   const int    ci = 0;
   f1( &i );  // ok
   f1( &ci ); // falsch, da f1() nicht verspricht, ci nicht zu ändern
   f2( &i );  // ok, auch wenn i nicht const ist
   f2( &ci ); // ok, da f2() verspricht, ci nicht zu ändern

Beim Aufruf f2( &i ) ist *p_i keine Konstante, auch wenn es in f2() so 
deklariert ist, sondern eine astreine Variable - sie wird nur in f2() 
nicht geändert.

Autor: Rolf Magnus (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Klaus Wachtler schrieb:
> Dosmo schrieb:
>> const int a; ist eine Konstante.const int *a; ist ein (variabler)
>> Zeiger auf eine Konstante.
>
> Jein.
> Genau genommen ist es eine Variable und mit dem const sagt man, daß man
> im Geltungsbereich dieser Deklaration diese Variable nicht ändern
> möchte.

Noch genauer genommen gibt es in C gar keine Konstanten (abgesehen von 
direkt als Zahl hingeschriebenen Werten). Das ist ja der Grund, warum so 
oft Makros als Ersatz dafür verwendet werden.

Autor: j.v. (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Decius schrieb:
> Aber Systemabhängig muß das ganze aber auch sein. Denn die Byteweiyse
> Addressierung der intelplattform ist bei ARM's nicht üblich.
>

Sie ist üblich.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Klaus Wachtler schrieb:

> void f2( const int * p_i )
> {
>    // jetzt nicht mehr möglich: *p_i++;
> }

Doch, *p_i++ geht sehr wohl, weil das *p_i nicht verändert.

Was hingegen nicht geht ist (*p_i)++.

Autor: Dosmo (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Klaus Wachtler schrieb:
> Dosmo schrieb:
>> const int a; ist eine Konstante.const int *a; ist ein (variabler)
>> Zeiger auf eine Konstante.
>
> Jein.
> Genau genommen ist es eine Variable und mit dem const sagt man, daß man
> im Geltungsbereich dieser Deklaration diese Variable nicht ändern
> möchte.

Absolut richtig.
Mir ging es um den Unterschied, ob man den Qualifier vor oder hinter den 
* setzt.

Autor: Klaus Wachtler (mfgkw)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Johann L. schrieb:
> Klaus Wachtler schrieb:
>
>> void f2( const int * p_i )
>> {
>>    // jetzt nicht mehr möglich: *p_i++;
>> }
>
> Doch, *p_i++ geht sehr wohl, weil das *p_i nicht verändert.
>
> Was hingegen nicht geht ist (*p_i)++.

ja, meinte ich natürlich.

Autor: Rolf Magnus (rmagnus)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Dosmo schrieb:
> Absolut richtig.
> Mir ging es um den Unterschied, ob man den Qualifier vor oder hinter den
> * setzt.

Generell bezieht sich der Qualifier auf das, was unmittelbar links davon 
steht. Und dann gibt es noch den Spezialfall, daß links nichts mehr 
kommt. Dann bezieht er sich stattdessen auf das, was unmittelbar rechts 
davon steht.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Dosmo schrieb:

> Mir ging es um den Unterschied, ob man den Qualifier vor oder hinter den
> * setzt.

In Gedanken trennt man die Deklaration in durch * getrennte Häppchen 
auf. Ein Qualifier wirkt nur auf sein eigenes Häppchen.

Damit ist auch klar, wie welcher Zugriff geschieht in
char f (const __flash char * const volatile __flash ** volatile * const p)
{
    return ****p;
}

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




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 erkennst du die Nutzungsbedingungen an.

webmaster@mikrocontroller.netImpressumNutzungsbedingungenWerbung auf Mikrocontroller.net