Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Qt analog to C struct?
Forum Updated to NodeBB v4.3 + New Features

Qt analog to C struct?

Scheduled Pinned Locked Moved Solved General and Desktop
29 Posts 4 Posters 8.3k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • mzimmersM Offline
    mzimmersM Offline
    mzimmers
    wrote on last edited by
    #18

    I'm probably being too fussy, but given how easily one can assign/copy QByteArray and QString objects, it's a shame IMO that there's no way to aggregate them as in a C struct. But it's probably their very flexibility that makes such use unfeasible.

    It's OK...I'm content to use memcpy_s, but it's just not attractive code.

    kshegunovK 1 Reply Last reply
    0
    • ? A Former User

      Yes, automatic range checking, increased safety against unintentional pointer mistakes, and compared to QByteArray, increased performance.

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by JonB
      #19

      @Wieland said in Qt analog to C struct?:

      Yes, automatic range checking,

      You said this in response to why std::array should be used/preferred. What "automatic range checking" are you saying it provides, under what circumstances?

      1 Reply Last reply
      0
      • mzimmersM mzimmers

        I'm probably being too fussy, but given how easily one can assign/copy QByteArray and QString objects, it's a shame IMO that there's no way to aggregate them as in a C struct. But it's probably their very flexibility that makes such use unfeasible.

        It's OK...I'm content to use memcpy_s, but it's just not attractive code.

        kshegunovK Offline
        kshegunovK Offline
        kshegunov
        Moderators
        wrote on last edited by kshegunov
        #20

        @mzimmers said in Qt analog to C struct?:

        I'm probably being too fussy,

        Not really, but it would help to know what you dislike about the above example and why you think you need to use memcpy?

        @JNBarchan said in Qt analog to C struct?:

        What "automatic range checking" are you saying it provides, under what circumstances?

        std::array<int, 3> x;
        int z = x[3]; //< Regular arrays allow this (generally)
        x[3] = 0;     //< Regular arrays mostly allow this too
        

        e.g. run this through your debugger:

        int main(int argc, char ** argv)
        {
            int z[2];
            z[2] = 0;
        }
        

        Read and abide by the Qt Code of Conduct

        JonBJ mzimmersM 2 Replies Last reply
        0
        • kshegunovK kshegunov

          @mzimmers said in Qt analog to C struct?:

          I'm probably being too fussy,

          Not really, but it would help to know what you dislike about the above example and why you think you need to use memcpy?

          @JNBarchan said in Qt analog to C struct?:

          What "automatic range checking" are you saying it provides, under what circumstances?

          std::array<int, 3> x;
          int z = x[3]; //< Regular arrays allow this (generally)
          x[3] = 0;     //< Regular arrays mostly allow this too
          

          e.g. run this through your debugger:

          int main(int argc, char ** argv)
          {
              int z[2];
              z[2] = 0;
          }
          
          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by JonB
          #21

          @kshegunov said in Qt analog to C struct?:

          @JNBarchan said in Qt analog to C struct?:
          What "automatic range checking" are you saying it provides, under what circumstances?

          std::array<int, 3> x;
          int z = x[3]; //< Regular arrays allow this (generally)
          x[3] = 0;     //< Regular arrays mostly allow this too
          

          I'm not understanding you. If you are saying with std::array<int, 3> x; then x[3] will be range checked, then I say it will not (that's why I asked)! Only x.at(3) will be. See docs. If your x[3] is range checked, that is a compiler-specific behaviour and/or you have to pass flags to compiler to ask it to do that.

          kshegunovK 1 Reply Last reply
          2
          • JonBJ JonB

            @kshegunov said in Qt analog to C struct?:

            @JNBarchan said in Qt analog to C struct?:
            What "automatic range checking" are you saying it provides, under what circumstances?

            std::array<int, 3> x;
            int z = x[3]; //< Regular arrays allow this (generally)
            x[3] = 0;     //< Regular arrays mostly allow this too
            

            I'm not understanding you. If you are saying with std::array<int, 3> x; then x[3] will be range checked, then I say it will not (that's why I asked)! Only x.at(3) will be. See docs. If your x[3] is range checked, that is a compiler-specific behaviour and/or you have to pass flags to compiler to ask it to do that.

            kshegunovK Offline
            kshegunovK Offline
            kshegunov
            Moderators
            wrote on last edited by kshegunov
            #22

            @JNBarchan said in Qt analog to C struct?:

            I say it will not

            Indeed, I'm in error.
            PS.
            My STL (g++ 7.2.x) doesn't even have an assertion there ... :|
            .at will throw an exception if out of bounds on the other hand.

            Read and abide by the Qt Code of Conduct

            JonBJ 1 Reply Last reply
            1
            • kshegunovK kshegunov

              @JNBarchan said in Qt analog to C struct?:

              I say it will not

              Indeed, I'm in error.
              PS.
              My STL (g++ 7.2.x) doesn't even have an assertion there ... :|
              .at will throw an exception if out of bounds on the other hand.

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by
              #23

              @kshegunov said in Qt analog to C struct?:

              PS.
              My STL (g++ 7.2.x) doesn't even have an assertion there ... :|
              .at will throw an exception if out of bounds on the other hand.

              Yup! But some places suggest "Enable the flag _GLIBCXX_DEBUG to do bounds checking on STL containers", though others claim that was still not the case for std::array. Might depend on compiler release. Also see https://stackoverflow.com/a/1290488/489865 for how Visual C++ does have explicit range checking, and https://stackoverflow.com/a/8375312/489865 using __glibcxx_check_subscript(), which you might put into your own code without tampering with the supplied libraries!

              kshegunovK 1 Reply Last reply
              0
              • JonBJ JonB

                @kshegunov said in Qt analog to C struct?:

                PS.
                My STL (g++ 7.2.x) doesn't even have an assertion there ... :|
                .at will throw an exception if out of bounds on the other hand.

                Yup! But some places suggest "Enable the flag _GLIBCXX_DEBUG to do bounds checking on STL containers", though others claim that was still not the case for std::array. Might depend on compiler release. Also see https://stackoverflow.com/a/1290488/489865 for how Visual C++ does have explicit range checking, and https://stackoverflow.com/a/8375312/489865 using __glibcxx_check_subscript(), which you might put into your own code without tampering with the supplied libraries!

                kshegunovK Offline
                kshegunovK Offline
                kshegunov
                Moderators
                wrote on last edited by kshegunov
                #24

                Well, as I mentioned in my first third post I'm not big on the new standards. Honestly, if it were me, I'd use the regular old statically sized arrays and leave the compiler to generate the copy constructor. Always has worked for me, and I don't see any good reason to use templates endlessly and unnecessarily, but that's me, the standards committee doesn't agree ...

                Read and abide by the Qt Code of Conduct

                JonBJ 1 Reply Last reply
                1
                • kshegunovK kshegunov

                  Well, as I mentioned in my first third post I'm not big on the new standards. Honestly, if it were me, I'd use the regular old statically sized arrays and leave the compiler to generate the copy constructor. Always has worked for me, and I don't see any good reason to use templates endlessly and unnecessarily, but that's me, the standards committee doesn't agree ...

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by JonB
                  #25

                  @kshegunov
                  Again, agree with you totally!

                  1 Reply Last reply
                  0
                  • kshegunovK kshegunov

                    @mzimmers said in Qt analog to C struct?:

                    I'm probably being too fussy,

                    Not really, but it would help to know what you dislike about the above example and why you think you need to use memcpy?

                    @JNBarchan said in Qt analog to C struct?:

                    What "automatic range checking" are you saying it provides, under what circumstances?

                    std::array<int, 3> x;
                    int z = x[3]; //< Regular arrays allow this (generally)
                    x[3] = 0;     //< Regular arrays mostly allow this too
                    

                    e.g. run this through your debugger:

                    int main(int argc, char ** argv)
                    {
                        int z[2];
                        z[2] = 0;
                    }
                    
                    mzimmersM Offline
                    mzimmersM Offline
                    mzimmers
                    wrote on last edited by mzimmers
                    #26

                    @kshegunov I'm using C structs and memcpy_s because in my mind it's simpler to use and understand than the C++ STL for arrays. For example:

                    struct
                    {
                        ...
                        uint8_t iv[16];
                        ...
                    }
                    ...
                    memcpy_s(msgHeader.iv, sizeof(msgHeader.iv), enc->getIv(), sizeof(msgHeader.iv));
                    

                    is admittedly unattractive, but it works. Consider the alternative:

                    struct
                    {
                        ...
                        std::array<uint8_t, 16> iv;
                    }
                    ...
                    std::copy(enc->getIv().begin(), enc->getIv().end(), msgHeader.iv.begin());
                    

                    This doesn't work (it causes a memory problem that results in a segmentation fault). The routine getIv is of type QByteArray.

                    kshegunovK 1 Reply Last reply
                    0
                    • mzimmersM mzimmers

                      @kshegunov I'm using C structs and memcpy_s because in my mind it's simpler to use and understand than the C++ STL for arrays. For example:

                      struct
                      {
                          ...
                          uint8_t iv[16];
                          ...
                      }
                      ...
                      memcpy_s(msgHeader.iv, sizeof(msgHeader.iv), enc->getIv(), sizeof(msgHeader.iv));
                      

                      is admittedly unattractive, but it works. Consider the alternative:

                      struct
                      {
                          ...
                          std::array<uint8_t, 16> iv;
                      }
                      ...
                      std::copy(enc->getIv().begin(), enc->getIv().end(), msgHeader.iv.begin());
                      

                      This doesn't work (it causes a memory problem that results in a segmentation fault). The routine getIv is of type QByteArray.

                      kshegunovK Offline
                      kshegunovK Offline
                      kshegunov
                      Moderators
                      wrote on last edited by kshegunov
                      #27

                      @mzimmers said in Qt analog to C struct?:

                      is admittedly unattractive, but it works.

                      What is enc->getIv()? Is it how you read that part of the header from the device?
                      You could for example do something like this:

                      struct
                      {
                          ...
                          uint8_t iv[16];
                          ...
                      } msgHeader;
                      
                      QByteArray iface = QByteArray::fromRawData(reinterpret_cast<const char *>(&msgHeader), sizeof(msgHeader));
                      

                      And then you can write and read directly into/from the byte array (on both sides when serializing/deserializing). This may require you to pack the structure however so you get sensible things from the reinterpret cast and it byte-order should be considered. Another thing, which is what I usually prefer is just to provide streaming from/to a data stream for the struct through
                      the << and >> operators. Then it's cleaner as you don't have any memcopy stuff outside of the struct/relevant functions. E.g.:

                      struct X
                      {
                          char a[10], b[5];
                      };
                      
                      QDataStream & operator << (QDataStream & out, const X & x)
                      {
                          out.writeRawData(x.a, sizeof(X::a));
                          out.writeRawData(x.b, sizeof(X::b));
                          return out;
                      }
                      
                      QDataStream & operator >> (QDataStream & in, X & x)
                      {
                          if (in.readRawData(x.a, sizeof(X::a)) != sizeof(X::a) || in.readRawData(x.b, sizeof(X::b)) != sizeof(X::b))
                              in.setStatus(QDataStream::ReadCorruptData);
                          return in;
                      }
                      

                      In this case you can stream the whole structure in one go from the binary representation:

                      QByteArray data; //< However this comes to you, if it's a raw C-array then attach a the byte array with `QByteArray::fromRawData`
                      
                      QDataStream in(&data, QIODevice::ReadOnly);
                      
                      X msgHandler;
                      in >> msgHandler;
                      
                      if (in.status() != QDataStream::Ok)
                          ; // Handle the error
                      

                      This is one possibility only, there are other options as well.

                      Read and abide by the Qt Code of Conduct

                      1 Reply Last reply
                      1
                      • mzimmersM Offline
                        mzimmersM Offline
                        mzimmers
                        wrote on last edited by
                        #28

                        @kshegunov thanks for the detailed reply. Your post made me aware of two things I hadn't ever noticed before: the fromRawData method, and the reinterpret_cast.

                        In answer to your question, getIv is just a convenience function to return a QByteArray containing a member object. The actual member is an array of 4 32-bit unsigned integers.

                        QByteArray Encryption::getIv()
                        {
                            QByteArray a = QByteArray((char *) m_iv, sizeof(m_iv));
                            return a;
                        }
                        
                        kshegunovK 1 Reply Last reply
                        0
                        • mzimmersM mzimmers

                          @kshegunov thanks for the detailed reply. Your post made me aware of two things I hadn't ever noticed before: the fromRawData method, and the reinterpret_cast.

                          In answer to your question, getIv is just a convenience function to return a QByteArray containing a member object. The actual member is an array of 4 32-bit unsigned integers.

                          QByteArray Encryption::getIv()
                          {
                              QByteArray a = QByteArray((char *) m_iv, sizeof(m_iv));
                              return a;
                          }
                          
                          kshegunovK Offline
                          kshegunovK Offline
                          kshegunov
                          Moderators
                          wrote on last edited by
                          #29

                          The reinterpret_cast is generally unsafe, so I'd advise against using it, especially if you have not taken into account all relevant peculiarities of the memory layout (byte-order, alignment and padding). The second part is my recommended approach and what I do in my own programs - clean and efficient enough.

                          Read and abide by the Qt Code of Conduct

                          1 Reply Last reply
                          0

                          • Login

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved