Forum: Compiler & IDEs gcc array an mehrdimensionales array zuweisen


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Karl K. (leluno)


Lesenswert?

Ich möchte per Pointer auf arrays zugreifen. Mehrere Arrays - also 
mehrere pointer in ein Pointer-array. Wie?
1
    u8  wr_bat_volt [] = { 0x00, 0x03, 0x02, 0x4B, 0x00, 0x01, 0xf4, 0x75 };
2
    u8* wr_bat_pow = { 0x00, 0x03, 0x02, 0x4E, 0x00, 0x01, 0xe4, 0x74 };
3
    u8* wr_soc = { 0x00, 0x03, 0x00, 0xD6, 0x00, 0x01, 0x64, 0x23 };
4
5
  
6
  volatile uint8_t *reg[] = { &wr_bat_volt, &wr_bat_pow, &wr_soc };
7
....
8
9
10
void main(void)
11
//
12
{
13
14
    wr_bat_pow[1]=0xff;//<==geht
15
       //*reg[1][1] = 0xFF; //<==geht nicht
16
    *reg[8*1+1]=6;//??

Danke für Nachsicht und Unterstützung

von Sherlock 🕵🏽‍♂️ (rubbel-die-katz)


Lesenswert?

Lösung:
1
#include <stdint.h>
2
3
typedef uint8_t u8;
4
5
u8 wr_bat_volt[] = { 0x00, 0x03, 0x02, 0x4B, 0x00, 0x01, 0xf4, 0x75 };
6
u8 wr_bat_pow[] = { 0x00, 0x03, 0x02, 0x4E, 0x00, 0x01, 0xe4, 0x74 };
7
u8 wr_soc[] = { 0x00, 0x03, 0x00, 0xD6, 0x00, 0x01, 0x64, 0x23 };
8
9
u8* reg[] = {wr_bat_volt, wr_bat_pow, wr_soc};
10
11
int main()
12
{
13
    reg[0][0] = 0xFF; // overwrite first byte in wr_bat_volt
14
    reg[2][7] = 0xAA; // overwrite last byte in wr_soc
15
}

Tipp: Benutze die Qt Creator IDE. Sie zeigt neben den fehlerhaften 
Zeilen nützliche Hilfestellungen an. Sie hilft auch, Fehler zu 
vermeiden, die der Compiler nicht melden würde.

Du solltest vielleicht wissen, dass die Namen der Arrays (hier: 
wr_bat_volt, wr_bat_pow, wr_soc) bereits Zeiger sind. Deswegen sind die 
beiden folgenden Funktionen praktisch identisch:
1
void function1(u8* myArray)
2
{
3
    for (int i=1; i<7; i++)
4
    {
5
        u8 v=myArray[i];
6
    }
7
}
8
9
void function2(u8 myArray[])
10
{
11
    for (int i=1; i<7; i++)
12
    {
13
        u8 v=myArray[i];
14
    }
15
}
16
17
int main()
18
{
19
    function1(wr_bat_volt);
20
    function2(wr_bat_volt);
21
}

: Bearbeitet durch User
von Jim M. (turboj)


Lesenswert?

Da hat man offensichtlich das Anfänger Tutorial übersprungen.

Denn Pointer auf Pointer (bzw Pointer auf Array, in C praktisch 
dasselbe) ist einer der Übergabeparameter für main auf allem was kein µC 
ist:
1
int main (int argc, char ** argv)
2
{ 
3
  //...
4
  return 0;
5
}

D.h. jedes Beispiel was die Aufruf Parameter eines Programms auswertet 
würde OP zeigen wie man das programmieren kann.

Die Sprache C ist ohne Literaturstudium mit totem Holz (Büchern) schwer 
verständlich.

von Karl K. (leluno)


Lesenswert?

Sherlock 🕵🏽‍♂️ schrieb:
> u8* reg[] = {wr_bat_volt, wr_bat_pow, wr_soc};

danke, das war es.

von Falk B. (falk)


Lesenswert?

Karl K. schrieb:
>> u8* reg[] = {wr_bat_volt, wr_bat_pow, wr_soc};
>
> danke, das war es.

Und warum der Zirkus? Hier reicht ein zweidimensionales Array.
1
u8 ups[3][8] = {
2
    { 0x00, 0x03, 0x02, 0x4B, 0x00, 0x01, 0xf4, 0x75 },
3
    { 0x00, 0x03, 0x02, 0x4E, 0x00, 0x01, 0xe4, 0x74 },
4
    { 0x00, 0x03, 0x00, 0xD6, 0x00, 0x01, 0x64, 0x23 }
5
};
6
7
ups[2][4] = 0xAA;

: Bearbeitet durch User
von Karl K. (leluno)


Lesenswert?

Falk B. schrieb:
> Und warum der Zirkus? Hier reicht ein zweidimensionales Array.

Die Befehlsfolgen sind unterschiedlich lang:
1
u8 wr_pvolt []= { 0x00, 0x03, 0x02, 0xA4, 0x00, 0x01, 0xc5, 0x80 };
2
u8 wr_off []= {0x00, 0x10, 0x00, 0x50, 0x00, 0x01, 0x01, 0x00, 0x00, 0x57, 0x90 };

von Bruno V. (bruno_v)


Lesenswert?

Karl K. schrieb:
> Die Befehlsfolgen sind unterschiedlich lang:
Das ist zwar hier O.T., aber bei Deinen Pointer-Kenntnissen solltest Du 
erwägen,  sie gleich lang zu machen und am Ende "leer" zu lassen. 
Alternativ die einzelnen Arrays mit Endekennung oder Längeninfo versehen 
und nur sequentiell abarbeiten (nicht 2D-indiziert).

von Harald K. (kirnbichler)


Lesenswert?

Karl K. schrieb:
> Die Befehlsfolgen sind unterschiedlich lang:

Wenn in ihnen nicht die Information über die Länge steckt, ist es eine 
sehr schlechte Idee, die in ein Pseudo-2D-Array packen zu wollen.

von Udo S. (urschmitt)


Lesenswert?

Wie Harald geschrieben hat. Du benötigst sehr wahrscheinlich die Länge 
der Befehlsfolge.
Also mach dir lieber für eine Befehlsfolge ein Struct mit einem 
sprechenden Namen z.B. "command" mit einer Variable für die Länge und 
einem Byte array für die eigentliche Folge.
Bzw. mach dir gleich ein typedef dafür.

: Bearbeitet durch User
von Karl K. (leluno)


Lesenswert?

1
     private void button4_Click(object sender, EventArgs e)
2
     {
3
         string line;
4
         string txt01 = "";
5
          string txt02 = "";
6
        bool cpy = false;
7
         bool whl = true;
8
     using (StreamWriter outputFile = new StreamWriter(@"C:\Users\karl\Desktop\rs485\2025_sim\sharp_types.h"))
9
     {
10
       System.IO.StreamReader file = new System.IO.StreamReader(@"C:\ra_vc\avr_sim_3\Form1.cs");
11
12
         while ((line = file.ReadLine()) != null && whl == true)
13
         {
14
             if (line.Contains("//start_01"))cpy = true;
15
             if(cpy==true )
16
             {
17
                 if (line.Contains("u8[]"))
18
                 {
19
                         int x1 = line.IndexOf(']')+1;
20
                         int x2 = line.IndexOf('=');
21
                         txt02 += line.Substring(x1, x2-x1)+",";
22
23
                         line = line.Replace("[]", "");
24
                     line = line.Replace ("=","[] =");
25
                 }
26
                 txt01 += line;
27
                  outputFile.WriteLine(line);
28
29
             }
30
              if (line.Contains("//end_01"))
31
             {
32
                cpy = false;
33
                whl = false;
34
                     txt01 += "u8* reg[] = { " + txt02 + "};";
35
                     outputFile.WriteLine("");
36
                  outputFile.WriteLine("u8* reg[] = { " + txt02 + "};");
37
            }
38
         }
39
40
     }
41
42
  }

generiert
1
         //start_01
2
            u8 wr_bat_volt [] = { 0x00, 0x03, 0x02, 0x4B, 0x00, 0x01, 0xf4, 0x75 };
3
            u8 wr_bat_pow [] = { 0x00, 0x03, 0x02, 0x4E, 0x00, 0x01, 0xe4, 0x74 };
4
            u8 wr_soc [] = { 0x00, 0x03, 0x00, 0xD6, 0x00, 0x01, 0x64, 0x23 };
5
            u8 wr_grid_pw [] = { 0x00, 0x03, 0x02, 0x83, 0x00, 0x01, 0x75, 0x8b };
6
            u8 wr_pvolt [] = { 0x00, 0x03, 0x02, 0xA4, 0x00, 0x01, 0xc5, 0x80 };
7
            u8 wr_off [] = {0x00, 0x10, 0x00, 0x50, 0x00, 0x01, 0x01, 0x00, 0x00, 0x57, 0x90 };   
8
            u8 wr_on [] = {0x00, 0x10, 0x00, 0x50, 0x00, 0x01, 0x01, 0x00, 0x01, 0x96, 0x50 };
9
        u8 wr_onoff [] = { 0x00, 0x03, 0x00, 0x50, 0x00, 0x01, 0x85, 0xca };
10
        u8 bat_on [] = { 0x02, 0x03, 0x00, 0x01, 0x00, 0x14, 0x14, 0x36 };
11
        u8 bat_off [] = { 0x02, 0x03, 0x00, 0x01, 0x00, 0x13, 0x55, 0xf4 };
12
     //end_01
13
14
u8* reg[] = {  wr_bat_volt , wr_bat_pow , wr_soc , wr_grid_pw , wr_pvolt , wr_off , wr_on , wr_onoff , bat_on , bat_off ,};
und wird über
#include "sharp_types.h"
eingebunden.

Vielleicht etwas oversized. Aber der Aufwand zum Testen des Programms 
ist so groß, dass es direkt auf dem avr sehr mühselig wäre.

von Harald K. (kirnbichler)


Lesenswert?

Ja, ganz toll. Und woher weiß das, was auf "u8* reg[]" zugreift, nun, 
wie lang eines der Elemente darin sind?
Diese Information geht verloren.

sizeof (wr_bat_volt)

funktioniert, aber

sizeof (reg[0])

liefert ganz was anderes.


Und .. u8? Wirklich? Spätestens seitdem es stdint.h gibt, ist sowas eine 
schlechte Idee.

von Karl K. (leluno)


Lesenswert?

Harald K. schrieb:
> Ja, ganz toll. Und woher weiß das, was auf "u8* reg[]" zugreift, nun,
> wie lang eines der Elemente darin sind?

Bislang gibt es nur 8- und 11-Byte-Befehle. Alle Befehle zum Messen 
haben 8Byte, alle Befehle zum Regeln haben 11Byte. Ein Problem, die 
Länge zu unterscheiden, stellte sich bislang nicht. Falls es auftreten 
sollte müsste die Länge ergänzt werden.
1
       private void sub_read_wr()
2
       { 
3
           
4
           bat_volt = sub_wr_tx_rx(reg[0], 8);
5
           bat_kw =   sub_wr_tx_rx(reg[1], 8);
6
           soc = sub_wr_tx_rx(reg[2], 8);
7
           grid_pw = sub_wr_tx_rx(reg[3], 8);
8
           pvolt = sub_wr_tx_rx(reg[4], 8);
9
....

von Klaus (feelfree)


Lesenswert?

Karl K. schrieb:
> Harald K. schrieb:
>> Ja, ganz toll. Und woher weiß das, was auf "u8* reg[]" zugreift, nun,
>> wie lang eines der Elemente darin sind?
>
> Bislang gibt es nur 8- und 11-Byte-Befehle. Alle Befehle zum Messen
> haben 8Byte, alle Befehle zum Regeln haben 11Byte. Ein Problem, die
> Länge zu unterscheiden, stellte sich bislang nicht. Falls es auftreten
> sollte müsste die Länge ergänzt werden.


Pfuschen für Fortgeschrittene.

von Bruno V. (bruno_v)


Lesenswert?

Karl K. schrieb:
> private void sub_read_wr()
>        {
>
>            bat_volt = sub_wr_tx_rx(reg[0], 8);
>            bat_kw =   sub_wr_tx_rx(reg[1], 8);
>            soc = sub_wr_tx_rx(reg[2], 8);
>            grid_pw = sub_wr_tx_rx(reg[3], 8);
>            pvolt = sub_wr_tx_rx(reg[4], 8);

Warum dann indiziert? der naive Ansatz wäre:
1
    bat_volt = sub_wr_tx_rx(wr_bat_volt, sizeof(wr_bat_volt));  
2
    bat_kw   = sub_wr_tx_rx(wr_bat_pow , sizeof(wr_bat_pow ));

von Klaus (feelfree)


Lesenswert?

Bruno V. schrieb:
> der naive Ansatz

Ist lesbar, während der Krampf mit den ungeeigneten 2-dim-Arrays zu 
write-only-code führt.

von Karl K. (leluno)


Lesenswert?

Klaus schrieb:
> Pfuschen für Fortgeschrittene.

ja - und? Solange es funktioniert sind mir Regeln relativ egal.

Bruno V. schrieb:
> Warum dann indiziert? der naive Ansatz wäre:
>     bat_volt = sub_wr_tx_rx(wr_bat_volt, sizeof(wr_bat_volt));
>     bat_kw   = sub_wr_tx_rx(wr_bat_pow , sizeof(wr_bat_pow ));

guter Vorschlag. Das Programm ist in der Entwicklung - werde ich 
vielleicht einbauen.


Frage:
Mein c#-programm ist ja nun in der Lage, gcc-code zu generieren. 
Wahrscheinlich kann man auch make über c# aufrufen. Dann hätte man 
irgendwo eine Datei main.hex in Maschinensprache für den avr. Es besteht 
eine serielle Verbindung zwischen avr und PC über RS485.

Kann man über diese Verbindung main.hex mittels Bootlader auf den avr 
schreiben?

: Bearbeitet durch User
von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Karl K. schrieb:
> gcc-code

Unterscheide bitte mal "C" und "GCC"...
- C ist die Programmiersprache
- GCC ist eine Sammlung von Compilern, inklusive einem C-Compiler, der 
ebenfalls "GCC" genannt wird
- Der GCC C Compiler hat wie alle anderen Compiler auch diverse 
spezifische Erweiterungen, d.h. Code der diese nutzt ist GCC-spezifisch, 
aber es ist dennoch C-Code
- Die GCC-Compiler können Code für viele verschiedene Plattformen 
generieren, insbesondere x86/amd64 (PC), ARM, und auch AVR. Die Variante 
der GCC-Compiler-Sammlung für AVR wird AVR-GCC genannt

Du generierst also C-Code. Den kannst du auch auf dem PC ausführen, 
solange du keine AVR-spezifischen Dinge nutzt. Dein Problem in diesem 
Thread ist ein gewöhnliches C-Problem, kein GCC-Problem, daher ist sogar 
der Threadtitel verkehrt.

Karl K. schrieb:
> Kann man über diese Verbindung main.hex mittels Bootlader auf den avr
> schreiben?

Du kannst einfach den avrdude aufrufen.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Sherlock 🕵🏽‍♂️ schrieb:
1
> void function1(u8* myArray)
2
> {
3
>     for (int i=1; i<7; i++)
4
>     {
5
>         u8 v=myArray[i];
6
>     }
7
> }

Arrays beginnen in C mit dem Index 0 und nicht 1. Außerdem läuft bei Dir 
der Index i durch die Prüfung i<7 nur bis 6. Damit wird dann nicht nur 
das erste Element, sondern auch noch das letzte (achte Element) 
ignoriert.

Korrekt wäre also bei 8 Elementen:
1
    for (int i=0; i<8; i++)    // 0,1,2,3,4,5,6,7

: Bearbeitet durch Moderator
von Sherlock 🕵🏽‍♂️ (rubbel-die-katz)


Lesenswert?

Frank M. schrieb:
> Arrays beginnen in C mit dem Index 0 und nicht 1 ...

Stimmt, da war ich wohl noch halb am Schlafen

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.