[C] Problem mit Zeigerarithmetik

rohrbold

Mitglied
Hallo beisammen,

irgendwie stehe ich voll auf dem Schlauch und komme einfach nicht dahinter, was an meiner Überlegung falsch ist. Ich möchte einen Byteblock erzeugen, der mittels einer Funktion, die mehrfach aufgerufen wird, aufgebaut wird. Folgendes ist ein Beispielcode, der nicht das tut, was er soll:
Code:
#include <stdio.h>

typedef unsigned char   u8;

void add_opt(void *rsp, void *data)
{
        *(u8 *) rsp = *(u8 *) data;
        printf("-> %p\n", rsp);
        rsp += 1;
}

int main()
{
        u8 rsp[2];
        u8 test = 'a';
        u8 test2 = 'b';
        add_opt(rsp, &test);
        add_opt(rsp, &test2);

        printf("%c %c\n", rsp[0], rsp[1]);

        return 0;
}
Ich will also den rsp Zeiger immer dann um ein Byte erhöhen, wenn ein neuer Wert dorthin geschrieben wurde. Hier tut sich aber leider nix, der Zeiger bleibt konstant. Also unterliege ich wohl in meinen Wissen zur Zeigerarithmetik einem Missverständnis. ;-)
Kennt jemand des Rätsels Lösung?
 
Hi.

Du hast anscheinend die Parameterübergabe von Funktionen noch nicht richtig verinnerlicht.

Parameter werden in C immer per Kopie (call by value) an Funktionen übergeben.

Wenn du also z.B. eine Funktion mit einem Pointer als Argument aufrufst, dann wird der Wert des Pointers kopiert und an die Funktion weitergereicht. Innerhalb der Funktion kannst du diese Kopie sooft und beliebig ändern - mit dem Original passiert nichts.

Du kannst innerhalb von Funktionen nur Werte ändern wenn du die Adresse von den Werten kennst, also die Lokation wo der Wert gespeichtert ist. Das geschieht dann über Pointer.

Willst du einen Pointer in einer Funktion vom Wert her verändern mußt du die Adresse des Pointers selbst übergeben.

Code:
void add_opt(void **rsp, void *data) {
  ...
  *(u8**)rsp += 1;
}
Gruß
 
Zuletzt bearbeitet:
Okay, das ist schonmal eine große Hilfe. Jetzt scheitert es bei mir nur noch daran, wie ich einen Zeiger auf das Array anlege, so dass ich diesen dann an die Funktion add_opt() übergeben kann. Hast Du dazu noch eine Idee?
 
Du machst es einfach so wie bei der Übergabe vom 2ten Parameter auch, du benutzt den Adressoperator.
Code:
add_opt(&rsp, &test);

Gruß
 
Das scheint irgendwie nicht zu gehen:
martin@bart:~$ gcc -W -Wall -o test test.c
test5.c: In Funktion »main«:
test5.c:17: Warnung: Übergabe des Arguments 1 von »add_opt« von inkompatiblem Zeigertyp
test5.c:18: Warnung: Übergabe des Arguments 1 von »add_opt« von inkompatiblem Zeigertyp


Hier der Code, den ich dafür jetzt verwendet habe:
Code:
#include <stdio.h>

typedef unsigned char   u8;

void add_opt(void **rsp, void *data)
{
        *(u8 *) rsp = *(u8 *) data;
        *(u8 **) rsp += 1;
        printf("-> %p\n", rsp);
}

int main()
{
        u8 rsp[2];
        u8 test = 'a';
        u8 test2 = 'b';
        add_opt(&rsp, &test);
        add_opt(&rsp, &test2);
        printf("%c %c\n", rsp[0], rsp[1]);

        return 0;
}
 
Ach ja. Dadurch das rsp ein Array ist liefert der Adressoperator immer den Anfang vom Array zurück. Das kommt daher weil natürlich auch der Anfang eines Arrays nicht verändert werden darf. D.h. das was du machen wolltest ist in C illegal.

Du könntest allerdings folgendes tun:
Code:
void* vp = rsp;
add_opt(&vp, &test);
Das ändert natürlich trotzdem nicht die Adresse des Arrays sondern den Wert des Pointers vp.

Außerdem mußt du innerhalb der Funktion der zusätzlichen Indirektion Rechnung tragen und rsp immer einmal mehr dereferenzieren als vorher. Oder du definierst in der Funktion der Einfachheit und Übersichtlichkeit halber noch eine neue Variable:
Code:
void add_opt(void **rspp, void *data)
{
        u8* rsp = *(u8**)rspp;

        *rsp = *(u8 *) data;
        *(u8**)rspp += 1;
}

Gruß
 
Zurück