[Gelöst] Konstruktor mit variablem uint8_t-Array



  • Moin.

    Ich versuche gerade, ein Array von Objekten zu initialisieren, die eine je Objekt unterschiedliche Bytesequenz im Konstruktor mitgegeben bekommen sollen. Die Klassendefinition:

    const uint8_t SEQLEN(24);
    class Sequence
    {
    public:
      uint8_t S_ptr;        // While parsing, index in seq successfully recognized
      uint8_t S_len;        // Length of sequence
      uint8_t S_offs;       // Offset of payload behind fully recognized sequence
      uint8_t S_dlen;       // Payload data length
      uint8_t S_unit;       // Unit code
      uint32_t S_div;       // divisor value
      uint16_t S_addr;      // Target address when writing I²C
      uint8_t S_seq[SEQLEN];    // Sequence of bytes to be recognized
    };
    

    Der Konstruktor dazu:

    Sequence::Sequence(uint8_t l, uint8_t o, uint8_t d, uint8_t u, uint32_t dv, uint16_t a, uint8_t s[])
    {
        S_ptr = 0;
        S_len = (l>SEQLEN) ? SEQLEN : l;
        S_offs = o;
        S_dlen = d;
        S_unit = u;
        S_div = dv;
        S_addr = a;
        memset(S_seq, 0, SEQLEN);
        memcpy(S_seq, s, S_len);
    }
    

    Und der vergebliche Versuch, ein Array dieser Objekte zu initialisieren:

    const uint8_t SEQUENCES(7);
    Sequence sequences[SEQUENCES] =
    {
      Sequence(8, 8, 4, 0x1B, 10, 2, {0x77, 0x07, 0x01, 0x00, 0x10, 0x07, 0x00, 0xFF } ),
      Sequence(8, 9, 4, 0x1E, 10, 6, {0x77, 0x07, 0x01, 0x00, 0x01, 0x08, 0x00, 0xFF } ),
      Sequence(8, 9, 4, 0x1E, 10, 10, {0x77, 0x07, 0x01, 0x00, 0x02, 0x08, 0x00, 0xFF } ),
      Sequence(8, 9, 4, 0x1E, 10, 14, {0x77, 0x07, 0x01, 0x00, 0x01, 0x08, 0x01, 0xFF } ),
      Sequence(8, 9, 4, 0x1E, 10, 18, {0x77, 0x07, 0x01, 0x00, 0x02, 0x08, 0x01, 0xFF } ),
      Sequence(8, 9, 4, 0x1E, 10, 22, {0x77, 0x07, 0x01, 0x00, 0x01, 0x08, 0x02, 0xFF } ),
      Sequence(8, 9, 4, 0x1E, 10, 26, {0x77, 0x07, 0x01, 0x00, 0x02, 0x08, 0x02, 0xFF } ),
    };
    

    Geht das prinzipiell und ich habe nur die falsche Syntax? Oder muss ich jedem einzelnen Objekt nach einem Konstruktoraufruf eines Knstruktors ohne Bytesequenz diese jeweils separat zuweisen (über eine Memberfunktion)?



  • Hab's selber gefunden - der "brace initializer" muss nochmal auf den richtigen Arraytyp gecastet werden:

    const uint8_t SEQUENCES(7);
    Sequence sequences[SEQUENCES] =
    {
      Sequence(8, 8, 4, 0x1B, 10, 2, (uint8_t []){0x77, 0x07, 0x01, 0x00, 0x10, 0x07, 0x00, 0xFF } ),
      Sequence(8, 9, 4, 0x1E, 10, 6, (uint8_t []){0x77, 0x07, 0x01, 0x00, 0x01, 0x08, 0x00, 0xFF } ),
      Sequence(8, 9, 4, 0x1E, 10, 10, (uint8_t []){0x77, 0x07, 0x01, 0x00, 0x02, 0x08, 0x00, 0xFF } ),
      Sequence(8, 9, 4, 0x1E, 10, 14, (uint8_t []){0x77, 0x07, 0x01, 0x00, 0x01, 0x08, 0x01, 0xFF } ),
      Sequence(8, 9, 4, 0x1E, 10, 18, (uint8_t []){0x77, 0x07, 0x01, 0x00, 0x02, 0x08, 0x01, 0xFF } ),
      Sequence(8, 9, 4, 0x1E, 10, 22, (uint8_t []){0x77, 0x07, 0x01, 0x00, 0x01, 0x08, 0x02, 0xFF } ),
      Sequence(8, 9, 4, 0x1E, 10, 26, (uint8_t []){0x77, 0x07, 0x01, 0x00, 0x02, 0x08, 0x02, 0xFF } ),
    };
    

    Geht so durch den Compiler - ob es das macht, was ich will, muss ich erst noch sehen 😉



  • @Miq sagte in [(Wahrscheinlich) gelöst] Konstruktor mit variablem uint8_t-Array:

    Geht so durch den Compiler

    Ja, mit einem C-Cast ist das einfach. Die Frage ist nur, was hinten raus kommt.



  • @manni66 sagte in [(Wahrscheinlich) gelöst] Konstruktor mit variablem uint8_t-Array:

    Ja, mit einem C-Cast ist das einfach. Die Frage ist nur, was hinten raus kommt.

    Was soll ich sagen? Das, was rauskommen sollte. Hat genau so funktioniert.😉



  • Sieht aus wie eine initializer_list mit int(!)-Einträgen, die dann hart auf uint8_t[] gecastet wird. Aber das kann ja nicht, sein man kann nicht auf einen Array-Typ casten. Bevor ich jetzt wieder den Standard wälze, was passiert denn da eigentlich und warum?



  • Also ich glaube nicht dass das Standard C++ ist.

    Clang frisst es, aber GCC meldet

    void fun(short[]);
    
    void test() {
        fun((short[]){1, 2, 3});
    }
    

    =>

    <source>: In function 'void test()':
    <source>:4:18: error: taking address of temporary array
        4 |     fun((short[]){1, 2, 3});
          |                  ^~~~~~~~~
    

    Und MSVC sagt dazu

    <source>(4): error C4576: a parenthesized type followed by an initializer list is a non-standard explicit type conversion syntax
    


  • Die VS Meldung sieht mir technisch besser aus, aber meine Güte ist das eine unnötig komplizierte Fehlermeldung.



  • Ich hoffe, ich habe nichts übersehen. Meine Lösung sähe so aus

    Nachtrag: Man sollte noch überprüfen, ob die initializer_list länger als 24 Bytes ist.

    #include <cstdlib>
    #include <iostream>
    #include <initializer_list>
    #include <array>
    
    static constexpr size_t SEQLEN(24);
    
    class Sequence {
    public:
        uint8_t S_ptr;        // While parsing, index in seq successfully recognized
        uint8_t S_len;        // Length of sequence
        uint8_t S_offs;       // Offset of payload behind fully recognized sequence
        uint8_t S_dlen;       // Payload data length
        uint8_t S_unit;       // Unit code
        uint32_t S_div;       // divisor value
        uint16_t S_addr;      // Target address when writing I²C
        uint8_t S_seq[SEQLEN] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};    // Sequence of bytes to be recognized
    
        Sequence (const uint8_t l, const uint8_t o, const uint8_t d, const uint8_t u,
            const uint32_t dv, const uint16_t a, std::initializer_list<uint8_t> seq);
    };
    
    
    Sequence::Sequence(const uint8_t l, const uint8_t o, const uint8_t d,
        const uint8_t u, const uint32_t dv, const uint16_t a, std::initializer_list<uint8_t> seq)
        : S_ptr(0), S_len((l>SEQLEN) ? SEQLEN : l), S_offs(o), S_dlen(d), S_unit(u),
            S_div(dv), S_addr(a)
    {
        std::copy (seq.begin(), seq.end(), S_seq);
    }
    
    const uint8_t SEQUENCES(7);
    
    Sequence sequences[SEQUENCES] = {
      Sequence(8, 8, 4, 0x1B, 10,  2, {0x77, 0x07, 0x01, 0x00, 0x10, 0x07, 0x00, 0xFF} ),
      Sequence(8, 9, 4, 0x1E, 10,  6, {0x77, 0x07, 0x01, 0x00, 0x01, 0x08, 0x00, 0xFF} ),
      Sequence(8, 9, 4, 0x1E, 10, 10, {0x77, 0x07, 0x01, 0x00, 0x02, 0x08, 0x00, 0xFF} ),
      Sequence(8, 9, 4, 0x1E, 10, 14, {0x77, 0x07, 0x01, 0x00, 0x01, 0x08, 0x01, 0xFF} ),
      Sequence(8, 9, 4, 0x1E, 10, 18, {0x77, 0x07, 0x01, 0x00, 0x02, 0x08, 0x01, 0xFF} ),
      Sequence(8, 9, 4, 0x1E, 10, 22, {0x77, 0x07, 0x01, 0x00, 0x01, 0x08, 0x02, 0xFF} ),
      Sequence(8, 9, 4, 0x1E, 10, 26, {0x77, 0x07, 0x01, 0x00, 0x02, 0x08, 0x02, 0xFF} ),
    };
    
    int main () {
        return EXIT_SUCCESS;
    }
    
    


  • @john-0 "Bezeichner" mit einem nichtssagenden Buchstaben? Seriously?



  • @Swordfish sagte in [Gelöst] Konstruktor mit variablem uint8_t-Array:

    @john-0 "Bezeichner" mit einem nichtssagenden Buchstaben? Seriously?

    Der Code ist zu 99,9% kopiert. Also was stört Dich?



  • @john-0 sagte in [Gelöst] Konstruktor mit variablem uint8_t-Array:

    Ich hoffe, ich habe nichts übersehen. Meine Lösung sähe so aus

    Nachtrag: Man sollte noch überprüfen, ob die initializer_list länger als 24 Bytes ist.

    Danke, es ist der G++, der da bei mir im Hintergrund werkelt. Ich kann Deine Lösung aber leider nicht so einfach übernehmen, da das Ganze auf einem Arduino Nano läuft und in der Entwicklungsumgebung (PlatformIO) schon die #includes für cstdlib usw. nicht funktionieren. Warum auch immer meine Version funktioniert, ist mir unklar, aber da sie es tut, werde ich es dabei belassen.

    Aber danke für Deinen Code - wieder was gelernt!



  • @Miq sagte in [Gelöst] Konstruktor mit variablem uint8_t-Array:

    Danke, es ist der G++, der da bei mir im Hintergrund werkelt. Ich kann Deine Lösung aber leider nicht so einfach übernehmen, da das Ganze auf einem Arduino Nano läuft und in der Entwicklungsumgebung (PlatformIO) schon die #includes für cstdlib usw. nicht funktionieren.

    Was für eine Version des g++ ist es?


Anmelden zum Antworten