Pointer Array schreiben / lesen

Gast #5338328
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..
#5338334
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.
Gast #5338336
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
}
#5338343
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);
Gast #5338351
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.
#5338352
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"}.
#5338355
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.
Gast #5338357
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
};
Gast #5338361
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?
Gast #5338377
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.
Gast #5338416
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
};
#5338427
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);
Gast #5338440
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren