Forum: Mikrocontroller und Digitale Elektronik Pointer Array schreiben / lesen


von Helmut A. (Gast)


Lesenswert?

1
typedef struct  
2
{
3
  /*
4
  *  Zu einer bestimmten Uhrzeit gemessene Temperatur
5
  */
6
  int8_t temp;
7
  
8
  /*
9
  *  Uhrzeit des gemessenen Wertes
10
  */
11
  char *time;
12
  
13
}tempStamp_t;
14
15
tempStamp_t stamp[] =
16
{
17
  { -12 , "00:00:00" },  // Niedrigst gemessene Temperatur
18
  { 12  , "00:00:00" },  // Höchst gemessene Temperatur
19
};

Hallo,

wenn Ich folgendes versuche..
1
    if ( sts3x.actual < sts3x.lowest )
2
    {
3
      sts3x.lowest = sts3x.actual;
4
      stamp[0].temp = sts3x.lowest;
5
      stamp[0].time = (char*)bcd_ttostr(rtc.hour,rtc.minute,rtc.second);
6
    }  
7
    else if ( sts3x.actual > sts3x.highest )
8
    {
9
      sts3x.highest = sts3x.actual;
10
      stamp[1].temp = sts3x.highest;
11
      stamp[1].time = (char*)bcd_ttostr(rtc.hour,rtc.minute,rtc.second);
12
      
13
      //stamp[1].time = "16:10:00";
14
    }

Und das ganze dann auslese, habe Ich in stamp[1].time genau die gleiche 
Uhrzeit wie in stamp[0]. Was mache Ich hier falsch?
Irgendetwas stimmt mit meiner Zeiger Thematik nicht so ganz..

von Felix U. (ubfx)


Lesenswert?

Schwer zu sagen, wenn man nicht weiß, wie sich bcd_ttostr verhält. 
Allerdings würde ich davon ausgehen, dass der Pointer, den die Funktion 
zurückgibt auf einen internen statischen Puffer zeigt, der 
logischerweise mit jedem Aufruf überschrieben wird. Also würde ich mal 
ein strrep um den Aufruf setzen.

von Helmut A. (Gast)


Lesenswert?

Felix U. schrieb:
> Schwer zu sagen, wenn man nicht weiß, wie sich bcd_ttostr verhält.
> Allerdings würde ich davon ausgehen, dass der Pointer, den die Funktion
> zurückgibt auf einen internen statischen Puffer zeigt, der
> logischerweise mit jedem Aufruf überschrieben wird. Also würde ich mal
> ein strrep um den Aufruf setzen.

Hier ist die Funktion
1
/* contains the time string */
2
char time[9];
3
char date[14];
4
5
6
char *bcd_ttostr(uint8_t hour, uint8_t min, uint8_t sec)
7
{
8
  /* BCD to ASCII */
9
  time[0] = (hour >> 4) + 48;
10
  time[1] = (hour & 0x0F) + 48;
11
  time[2] = ':';
12
  time[3] = (min >> 4) + 48;
13
  time[4] = (min & 0x0F) + 48;
14
  time[5] = ':';
15
  time[6] = (sec >> 4) + 48;
16
  time[7] = (sec & 0x0F) + 48;
17
  time[8] = '\0';
18
  
19
  return time;
20
}

von Felix U. (ubfx)


Lesenswert?

Helmut A. schrieb:
> Hier ist die Funktion

Dann ist es so wie ich vermute habe. Der "time" Puffer wird bei jedem 
Aufruf überschrieben. Du musst ihn also kopieren bevor du die Funktion 
neu aufrufst. Ein Ansatz dafür wäre strrep.

Das bringt dich aber in die unangenehme Situation, dynamisch Speicher 
allozieren und freigeben zu müssen.

Entweder du änderst also deine Struktur so, dass du die RTC-Werte als 
Zahlen speicherst und dann nur für die Ausgabe in Text umwandelst, oder 
du erzeugst direkt für jedes Element einen ausreichend großen Puffer:
1
typedef struct  
2
{
3
  /*
4
  *  Zu einer bestimmten Uhrzeit gemessene Temperatur
5
  */
6
  int8_t temp;
7
  
8
  /*
9
  *  Uhrzeit des gemessenen Wertes
10
  */
11
  char time[9];
12
  
13
}tempStamp_t;

und machst dann
1
strcpy(stamp[0].time, (char*)bcd_ttostr(...));

oder, wenn du gerade dabei bist, kannst du dir die unnötige Kopieraktion 
auch sparen und die Funktion so ändern:
1
void bcd_ttostr(char* time, uint8_t hour, uint8_t min, uint8_t sec)
2
{
3
  /* BCD to ASCII */
4
  time[0] = (hour >> 4) + 48;
5
  time[1] = (hour & 0x0F) + 48;
6
  time[2] = ':';
7
  time[3] = (min >> 4) + 48;
8
  time[4] = (min & 0x0F) + 48;
9
  time[5] = ':';
10
  time[6] = (sec >> 4) + 48;
11
  time[7] = (sec & 0x0F) + 48;
12
  time[8] = '\0';
13
}

Und den Aufruf dann direkt so:
1
bcd_ttostr(stamp[0].time, 1, 2, 3);

von Helmut A. (Gast)


Lesenswert?

Felix U. schrieb:
> Dann ist es so wie ich vermute habe. Der "time" Puffer wird bei jedem
> Aufruf überschrieben. Du musst ihn also kopieren bevor du die Funktion
> neu aufrufst. Ein Ansatz dafür wäre strrep.

Verstehe Ich jetzt mal nicht ganz.
Ich möchte doch das der "time" Puffer überschrieben wird wenn sich die 
Uhrzeit ändert.

von Daniel A. (daniel-a)


Lesenswert?

"00:00:00" ist eine ein constantes char array, dass nicht verändert 
werden darf. Aus historischen gründen darf ein char* damit initialisiert 
werden. Der compiler wird vermutlich die beiden identischen 
Stringconstanten nur einmal speichern, wodurch stamp[0].time == 
stamp[1].time. Ändere entweder "char *time" zu "char time[9]", oder 
initialisere es mit einem compound literal (char[]){"00:00:00"}.

von Felix U. (ubfx)


Lesenswert?

Helmut A. schrieb:
> Verstehe Ich jetzt mal nicht ganz.
> Ich möchte doch das der "time" Puffer überschrieben wird wenn sich die
> Uhrzeit ändert.

In deiner Version gibt es nur einen einzigen Time-Puffer, auf den sowohl 
der Eintrag für den Minimal, als auch der für den Maximalwert zeigt. Der 
einzelne Puffer kann logischerweise auch nur eine einzelne Uhrzeit 
beinhalten.

Du brauchst also mindestens zwei Puffer, um zwei Uhrzeiten speichern zu 
können.

von Helmut A. (Gast)


Lesenswert?

Daniel A. schrieb:
> "00:00:00" ist eine ein constantes char array, dass nicht
> verändert
> werden darf. Aus historischen gründen darf ein char* damit initialisiert
> werden. Der compiler wird vermutlich die beiden identischen
> Stringconstanten nur einmal speichern, wodurch stamp[0].time ==
> stamp[1].time. Ändere entweder "char *time" zu "char time[8]", oder
> initialisere es mit einem compound literal (char[]){"00:00:00"}.
Meinst du so?
1
tempStamp_t stamp[] =
2
{
3
  { 0 , (char[]){"00:00:00"} },
4
  { 0 , (char[]){"00:00:00"} },      
5
};

von Helmut A. (Gast)


Lesenswert?

Felix U. schrieb:
> Helmut A. schrieb:
>> Verstehe Ich jetzt mal nicht ganz.
>> Ich möchte doch das der "time" Puffer überschrieben wird wenn sich die
>> Uhrzeit ändert.
>
> In deiner Version gibt es nur einen einzigen Time-Puffer, auf den sowohl
> der Eintrag für den Minimal, als auch der für den Maximalwert zeigt. Der
> einzelne Puffer kann logischerweise auch nur eine einzelne Uhrzeit
> beinhalten.
>
> Du brauchst also mindestens zwei Puffer, um zwei Uhrzeiten speichern zu
> können.
Ich dachte das tue Ich hiermit
1
tempStamp_t stamp[ ] =
2
{
3
  { -12 , "00:00:00 " },  // Niedrigst gemessene Temperatur
4
  { 12  , "00:00:00 " },  // Höchst gemessene Temperatur
5
};
Sage Ich dem Compiler dadurch nicht das er mir für "00:00:00" 9 Bytes 
reservieren soll?

von Daniel A. (daniel-a)


Lesenswert?

@Helmut A. (Gast)

Ich hatte übersehen, dass bcd_ttostr nur einen Pointer auf einen anderen 
Buffer zurück gibt, und nicht den bestehenden übergeben bekommt und 
überschreibt. Sorry führ die Verwirrung.

von Felix U. (ubfx)


Lesenswert?

Helmut A. schrieb:
> Sage Ich dem Compiler dadurch nicht das er mir für "00:00:00" 9 Bytes
> reservieren soll?

Nein. Das musst du schon in der Struktur machen.

von Helmut A. (Gast)


Lesenswert?

Felix U. schrieb:
> Helmut A. schrieb:
>> Sage Ich dem Compiler dadurch nicht das er mir für "00:00:00" 9 Bytes
>> reservieren soll?
>
> Nein. Das musst du schon in der Struktur machen.
Wie kann man das noch machen?
1
char *buff[2][9]
Würde das gehen?

von Felix U. (ubfx)


Lesenswert?

Helmut A. schrieb:
> char *buff[2][9]
> Würde das gehen?

char buff[2][9] würde noch Sinn ergeben. Warum nimmst du nicht die 
Variante die ich oben vorgeschlagen habe?

von Helmut A. (Gast)


Lesenswert?

Felix U. schrieb:
> Helmut A. schrieb:
>> char *buff[2][9]
>> Würde das gehen?
>
> char buff[2][9] würde noch Sinn ergeben. Warum nimmst du nicht die
> Variante die ich oben vorgeschlagen habe?

Diese Funktion benutze Ich schon an anderen Stellen erfolgreich so muss 
Ich nicht ständig noch einen Parameter übergeben und setze so nur auf 
einen Puffer. Jetzt wirds mir auch klar wieso das nicht funktioniert.

von Helmut A. (Gast)


Lesenswert?

Könnte es mit einem Zeiger nicht auch funktionieren?
1
typedef struct  
2
{
3
  /*
4
  *  Zu einer bestimmten Uhrzeit gemessene Temperatur
5
  */
6
  int8_t temp;
7
  
8
  /*
9
  *  Uhrzeit des gemessenen Wertes
10
  */
11
  char time[9];
12
  
13
  /*
14
  *  Zeiger auf den Temperatur String
15
  */
16
  char *ptr;
17
  
18
}tempStamp_t;
19
20
tempStamp_t stamp[2] =
21
{
22
  { 0 , "00:00:00" , stamp[0].time },
23
  { 0 , "10:00:00" , stamp[1].time },
24
};

von Daniel A. (daniel-a)


Lesenswert?

Helmut A. schrieb:
> Könnte es mit einem Zeiger nicht auch funktionieren?

Der Zeiger nützt dir genau garnichts. Du weisst ja bereits, wo deine 
zwei Buffer sind, und wen du wie vorher wieder die Zeiger auf den 
gleichen Buffer zeigen lässt hasst du wieder das gleiche Problem. Du 
könntest aber memcpy verwenden, sofern du die Funktion bcd_ttostr nicht 
in unterschiedlichen Threads oder in Signal handlern nutzt.
1
typedef struct  
2
{
3
  int8_t temp;
4
  char time[9];
5
}tempStamp_t;
6
...
7
memcpy(stamp[0].time,bcd_ttostr(rtc.hour,rtc.minute,rtc.second),9);

von steve41993 (Gast)


Lesenswert?

Hallo Helmut A.

ich würde es folgendermaßen versuchen, wenn du die Funktion 'bcd_ttostr' 
nicht verändern willst:
1
typedef struct  
2
{
3
  /*
4
  *  Zu einer bestimmten Uhrzeit gemessene Temperatur
5
  */
6
  int8_t temp;
7
  
8
  /*
9
  *  Uhrzeit des gemessenen Wertes
10
  */
11
  char time[9];
12
  
13
}tempStamp_t;
14
15
tempStamp_t stamp[] =
16
{
17
  { -12 , "00:00:00" },  // Niedrigst gemessene Temperatur
18
  { 12  , "00:00:00" },  // Höchst gemessene Temperatur
19
};
1
    if ( sts3x.actual < sts3x.lowest )
2
    {
3
      sts3x.lowest = sts3x.actual;
4
      stamp[0].temp = sts3x.lowest;
5
      memcpy(stamp[0].time, (char*)bcd_ttostr(rtc.hour,rtc.minute,rtc.second), 9);
6
    }  
7
    else if ( sts3x.actual > sts3x.highest )
8
    {
9
      sts3x.highest = sts3x.actual;
10
      stamp[1].temp = sts3x.highest;
11
      memcpy(stamp[1].time, (char*)bcd_ttostr(rtc.hour,rtc.minute,rtc.second), 9);
12
      //stamp[1].time = (char*)bcd_ttostr(rtc.hour,rtc.minute,rtc.second);
13
      //so würde dein stamp[1].time Pointer auf den Buffer zeigen. Der Inhalt wird ja nicht in stamp[1].time kopiert.
14
      
15
      //stamp[1].time = "16:10:00";
16
    }

Dein Problem ist, dass nach dem beide stamp[0].time und stamp[1].time 
gesetzt wurden diese auf den Buffer zeigen. Somit repräsentieren diese 
immer den aktuellen Inhalt des Buffers.

Grüße
steve41993

von Helmut A. (Gast)


Lesenswert?

So klappt es jetzt ja auch..
1
strcpy ( stamp[1].time , bcd_ttostr(rtc.hour,rtc.minute,rtc.second) );

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.