Datum:
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?
Datum:
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.
Datum:
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)
Datum:
Datum:
Danke, bin noch am lesen, garnicht schlecht.
Datum:
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?
Datum:
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.
Datum:
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.
Datum:
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
Datum:
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.
Datum:
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.
Datum:
habe ja geschrieben, das das Systemabhängig ist.
Datum:
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.
Datum:
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
Datum:
ok, hast recht. Ist wieder gerade gerückt. :-)
Datum:
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.
Datum:
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.
Datum:
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.
Datum:
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.
Datum:
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)++.
Datum:
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.
Datum:
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.
Datum:
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.
Datum:
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; } |