Forum: PC-Programmierung Hilfe zu Ansi C Code


von Gast (Gast)


Lesenswert?

Ich hab in meinem Projekt ein Array mit dem Namen Daten definiert.
Dieses Array hat eine Größe von 100.
--> double Daten[100];
Ich möchte innerhalb auf das Array zugreifen und durch einen Zeiger 
dieses Array mit Zahlen befüllen. Leider funktioniert dies nicht so, wie 
ich es implementiert habe. Siehe folgender Code:
1
int *ptr;
2
ptr = pthis->Daten;
3
for (i = 0; i < 100; i++)
4
{
5
   *ptr = i;
6
   ptr++;
7
}

In dem Array Daten stehen die fortlaufenden Zaheln nicht drin. Waron 
könnte dies liegen?

von Karl H. (kbuchegg)


Lesenswert?

Gast schrieb:
> Ich hab in meinem Projekt ein Array mit dem Namen Daten definiert.
> Dieses Array hat eine Größe von 100.
> --> double Daten[100];
> Ich möchte innerhalb auf das Array zugreifen und durch einen Zeiger
> dieses Array mit Zahlen befüllen. Leider funktioniert dies nicht so, wie
> ich es implementiert habe. Siehe folgender Code:
>

Hat den der Compiler dazu gar keine Meinung?

> int *ptr;

Aha. ptr ist also ein Zeiger auf int

> ptr = pthis->Daten;

und Daten hast du uns oben als ein double Array untergejubelt

    int != double

> In dem Array Daten stehen die fortlaufenden Zaheln nicht drin. Waron
> könnte dies liegen?

Wenn das nur ein Tippfehler war, dann poste den Code direkt aus deinem 
Editor. Und zeig auch ein wenig mehr. Aus dem Schnipsel ist nicht 
erkennbar, welche Fehler du noch gemacht haben könntest. Zb. könnte ich 
mir ein Gewirx mit lokalen Variablen vorstellen, etc.

von Klaus W. (mfgkw)


Lesenswert?

1. ist das kein vollständiges Beispiel; z.B. sehe ich nicht, wo
pthis herkommen soll.

2. ist ptr ein Zeiger auf int, während in Daten[]
angeblich (?) double stehen sollen. Das kann nicht gut gehen.

3. hat der Compiler bestimmt Warnungen ausgegeben, um die
sich offenbar niemand kümmert.
Stattdessen wird erstmal im Forum gefragt.

4. kommt mir Gast (Gast) irgendwie bekannt vor, habe ich bestimmt
schon mal gelesen?

von tobi (Gast)


Lesenswert?

Du musst auf jeden Fall mehr Code zeigen.

Wenn du einfach ein double Array haben möchtest und dann einen zeiger 
drauf und über diesen Zeiger das Array initialisieren dann könnte es 
einfach wie folgt aussehen
1
double daten[100];
2
double *ptr = daten; // oder &daten[0]
3
4
int i;
5
6
for(i = 0; i < 100; i++)
7
    *ptr++ = i;

von Peter S. (psavr)


Lesenswert?

Wieso nich ganz einfach...
1
#define DATEN_ARRAY_SIZE 100
2
3
double daten[DATEN_ARRAY_SIZE];
4
int i;
5
6
for(i = 0; i < DATEN_ARRAY_SIZE; i++)
7
{
8
    daten[i] = i;
9
}

von Klaus W. (mfgkw)


Lesenswert?

iss zu einfach, das kann ja jeder.

von Johnny (Gast)


Lesenswert?

..und auch viel zu übersichtlich. Mit solchem Code kann man sich in 
einer Firma nicht unabkömmlich machen.

von zwieblum (Gast)


Lesenswert?

also ich fin'd ja das da viel eleganter:

*ptr++ = i++;

:-)

von Klaus W. (mfgkw)


Lesenswert?

nee, wenn schon dann kann man auf i auch gleich verzichten!
1
#define DATEN_ARRAY_SIZE 100
2
3
double daten[DATEN_ARRAY_SIZE];
4
double *p_daten;
5
6
for( p_daten = daten; p_daten < daten + DATEN_ARRAY_SIZE; p_daten++ )
7
{
8
    *p_daten = p_daten - daten;
9
}

Das verwirrt doch viel schöner, und nach dem Optimierer kommt 
wahrscheinlich dasselbe raus.

von Daniel (root) (Gast)


Lesenswert?

1
double * data = new double[100], * pdata = data;
2
*pdata = 0.0;
3
while(*pdata < 100.0)
4
    *(pdata+1) = *pdata+1;
5
// ...
6
delete [] data;

mit so einem code macht man sich unverzichbar ;-)

kann man auch
1
*++pdata = *pdata+1;
verwenden?

von Klaus W. (mfgkw)


Lesenswert?

kann man schon, aber das Ergebnis ist nicht definiert.

und mit ...<100.0 kann man auch versehentlich einen Durchlauf
zuviel haben; dann kommt man wenigstens ans schwarze Brett mit
dem Bug der Woche.
Sicherer und viel klarer wäre ...<99.572448

von Karl H. (kbuchegg)


Lesenswert?

Daniel (root) schrieb:

> kann man auch
>
1
> *++pdata = *pdata+1;
2
>
> verwenden?

Ähm .... nein. Das ist 'undefined behaviour'

(Als Daumenregel: sobald eine Variable in einem Ausdruck 2 mal vorkommt 
und an einer Stelle steht ++ oder -- vor/hinter der Variablen, hast du 
undefined beh.)

von Daniel (root) (Gast)


Lesenswert?

wobei hier die Quelle nicht zwei mal beschrieben wird ...
wie im typischen
1
i=i++;

hier kommt es wohl auf die Zugriffsreihenfolge read/write oder
write/read.

Ich werde es mir merken ;-)

von Daniel (root) (Gast)


Lesenswert?

lispisch ...
1
(assign (dereference pdata) (add (dereference (incr pdata)) 1))
2
3
(assign (dereference (incr pdata)) (add (dereference pdata) 1))

interessant ist, dass man in lispsyntax keine Zweideutigkeiten
erzeugen kann.

von Sven P. (Gast)


Lesenswert?

Daniel (root) schrieb:
> wobei hier die Quelle nicht zwei mal beschrieben wird ...
> wie im typischen
>
1
> i=i++;
2
>
>
> hier kommt es wohl auf die Zugriffsreihenfolge read/write oder
> write/read.
Es ist ebenfalls undefiniertes Verhalten, da bin ich auch drüber 
gestolpert, die Diskussion gabs neulich noch hier mit sehr anschaulichen 
Beispielen. Such halt mal.

von Karl H. (kbuchegg)


Lesenswert?

Daniel (root) schrieb:
>
1
> (assign (dereference pdata) (add (dereference (incr pdata)) 1))
2
> 
3
> (assign (dereference (incr pdata)) (add (dereference pdata) 1))
4
>
>
> interessant ist, dass man in lispsyntax keine Zweideutigkeiten
> erzeugen kann.

Keine Ahnung wie das in Lisp ist. Ist es da exakt definiert in welcher 
Reihenfolge Listen ausgewertet werden.

(assign a b)

ok es ist klar, dass sowohl a als auch b evaluiert werden müssen, ehe 
der assign seine Arbeit tun kann.
Aber ist auch geregelt, ob zuerst eval(a) und dann eval(b) gemacht wird 
oder umgekehrt, oder ist das freigestellt.

In C ist das freigestellt. D.h. ein "Lisp compiler - C-like" (ich hoffe 
man versteht was ich damit meine), könnte

 (assign (dereference pdata) (add (dereference (incr pdata)) 1))

mit diesen Schritten implementieren

  eval(dereference pdata)
  eval(add (dereference (incr pdata)) 1)
  assign

Er könnte aber auch

  eval(add (dereference (incr pdata)) 1)
  eval(dereference pdata)
  assign

implementieren. Damit hast du schon mal einen Teil des undefinierten 
Verhaltens. In C-Speak: Es ist nicht festgelegt, ob zuerst der rechte 
oder der linke Teil bei einer Zuweisung ausgewertet wird oder gar eine 
Mischung aus beidem.

Der andere Teil des undef. Verhaltens kommt daher, dass nicht festgelegt 
ist, wann genau der Increment bei ++ zu erfolgen hat. C fordert 
lediglich, dass dieser Nebeneffekt spätestens beim nächsten Sequenzpunkt 
(sequence point) abgeschlossen sein muss.

Sequence Points sind im wesentlichen
 * alle ;
 * Ein Funktionsaufruf
 * fällt mir grade nicht ein

D.h. der Compiler darf in

  *++pdata = *pdata+1;

den Inkrement von pData rumschieben wie er lustig ist. Die Anweisung 
kann komplett abgearbeitet sein und pdata hat überall denselben Wert und 
erst kurz bevor in der logischen Sequenz der ; kommt wird pdata auf den 
nächsten Wert gesetzt. Ist eine Möglichkeit. Der Compiler kann den 
increment von pdata aber auch vorziehen soweit er möchte (und es die 
Datenflussanalyse erlaubt). Ob also deine rechte Seite in obiger 
Zuweisung noch den vorhergehenden oder bereits den incrementierten Wert 
von pdata sieht, ist nicht definiert.

Denn eines steht fest: Ein = ist kein Sequencepoint, auch wenn viele 
das gerne implizit annehmen.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Daniel (root) schrieb:
>
1
> double * data = new double[100], * pdata = data;
2
> *pdata = 0.0;
3
> while(*pdata < 100.0)
4
>     *(pdata+1) = *pdata+1;
5
> // ...
6
> delete [] data;
7
>
>
> mit so einem code macht man sich unverzichbar ;-)

Mit solchem Code machst du sich für die Firma verzichtbar :-)

1) Addition von double ist nicht assoziativ.
2) Erst wenn die 100 schon geschrieben ist, hörst du auf autsch

Johann

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.