Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. hacking std::copy to use pointers

hacking std::copy to use pointers

Scheduled Pinned Locked Moved Unsolved C++ Gurus
11 Posts 4 Posters 5.0k Views 4 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.
  • jeremy_kJ Offline
    jeremy_kJ Offline
    jeremy_k
    wrote on last edited by
    #2

    I'm confused by that code snippet. The following compiles with a selection of compilers for C++11 and later.

    #include <cstdint>
    #include <algorithm>
    #if _cplusplus >= 202002L
    #include <span>
    #endif
    
    void test(uint8_t *input, size_t length, uint8_t *output)
    {
    #if _cplusplus >= 202002L
        std::span s{input, length};
        std::copy(s.begin(), s.end(), output);
    #endif
        std::copy(input, input + length, output);
    }
    

    std::span is a C++20 non-owning wrapper container for contiguous sequences, which might meet your last request.

    I don't understand how std::copy() using a separately passed length is superior to memcpy(). I do understand following arbitrary rules to avoid spending time discussing arbitrary rules.

    Was the original formulation of the question referring to C++20 ranges?

    Asking a question about code? http://eel.is/iso-c++/testcase/

    1 Reply Last reply
    2
    • Kent-DorfmanK Offline
      Kent-DorfmanK Offline
      Kent-Dorfman
      wrote on last edited by Kent-Dorfman
      #3

      No c++20...It is to conform to AUTOSAR "Guidelines for the use of the C++14 language in critical and safety related systems". It's a coding safety standard where much of it makes sense and some of it is pure OCD on the part of the members of the standards committee. LOL Point is, trying to slowly phase out C-ish code but still working on low level embedded systems so "pointers are king". Standard requires documentation and justification each time a rule is violated.

      A custom allocator for std::vector may be a work-around but I had hoped something already existed for this use-case.

      Yes, this compiles but give erroneous results.

      void test(const uint8_t *input, const size_t length, uint8_t *output) {
          std::copy(input, input + length, output);
      }
      

      and this is the other real use-case that fails...moving into or out of the destPtr buffer

      uint32_t ip = ::htonl((127U << 24U) | 1U);
      std::copy(&ip, &ip + sizeof(ip), destPtr);
      
      JKSHJ 1 Reply Last reply
      0
      • Kent-DorfmanK Kent-Dorfman

        No c++20...It is to conform to AUTOSAR "Guidelines for the use of the C++14 language in critical and safety related systems". It's a coding safety standard where much of it makes sense and some of it is pure OCD on the part of the members of the standards committee. LOL Point is, trying to slowly phase out C-ish code but still working on low level embedded systems so "pointers are king". Standard requires documentation and justification each time a rule is violated.

        A custom allocator for std::vector may be a work-around but I had hoped something already existed for this use-case.

        Yes, this compiles but give erroneous results.

        void test(const uint8_t *input, const size_t length, uint8_t *output) {
            std::copy(input, input + length, output);
        }
        

        and this is the other real use-case that fails...moving into or out of the destPtr buffer

        uint32_t ip = ::htonl((127U << 24U) | 1U);
        std::copy(&ip, &ip + sizeof(ip), destPtr);
        
        JKSHJ Offline
        JKSHJ Offline
        JKSH
        Moderators
        wrote on last edited by JKSH
        #4

        @Kent-Dorfman said in hacking std::copy to use pointers:

        Is there a way to hack std::copy so that it can take simple uint8_t* as range limits

        You don't need to hack it; the code you posted in your original post should already work (assuming that ADDRESS, DESTINATION, and length are correct).

        Yes, this compiles but give erroneous results.

        void test(const uint8_t *input, const size_t length, uint8_t *output) {
            std::copy(input, input + length, output);
        }
        

        Erroneous how?

        and this is the other real use-case that fails...moving into or out of the destPtr buffer

        uint32_t ip = ::htonl((127U << 24U) | 1U);
        std::copy(&ip, &ip + sizeof(ip), destPtr);
        

        This code will try to copy 16 bytes, not 4 bytes. You want std::copy(&ip, &ip + 1, destPtr);

        Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

        Kent-DorfmanK 1 Reply Last reply
        2
        • JKSHJ JKSH

          @Kent-Dorfman said in hacking std::copy to use pointers:

          Is there a way to hack std::copy so that it can take simple uint8_t* as range limits

          You don't need to hack it; the code you posted in your original post should already work (assuming that ADDRESS, DESTINATION, and length are correct).

          Yes, this compiles but give erroneous results.

          void test(const uint8_t *input, const size_t length, uint8_t *output) {
              std::copy(input, input + length, output);
          }
          

          Erroneous how?

          and this is the other real use-case that fails...moving into or out of the destPtr buffer

          uint32_t ip = ::htonl((127U << 24U) | 1U);
          std::copy(&ip, &ip + sizeof(ip), destPtr);
          

          This code will try to copy 16 bytes, not 4 bytes. You want std::copy(&ip, &ip + 1, destPtr);

          Kent-DorfmanK Offline
          Kent-DorfmanK Offline
          Kent-Dorfman
          wrote on last edited by
          #5
          This post is deleted!
          1 Reply Last reply
          0
          • Kent-DorfmanK Offline
            Kent-DorfmanK Offline
            Kent-Dorfman
            wrote on last edited by
            #6

            std::copy(&ip, &ip + sizeof(ip), destPtr); was definitely a goof on my part.

            1 Reply Last reply
            0
            • Kent-DorfmanK Offline
              Kent-DorfmanK Offline
              Kent-Dorfman
              wrote on last edited by
              #7

              another fly in the ointment that makes std::copy unsuitable for moving memory buffers around:

              Given the above example of copying the bytes of a uint32_t to an arbitrary memory location, the destPtr (being of type uint8_t*) wont allow std::copy to copy the whole range from the input iteratores. It only copies one byte! Some would argue that destPtr should then be of type uint32_t* but that could cause other problems since there is no guarantee that the destination address would be word aligned...IOW, I don't necessarily want it to be aligned, but instead packed.

              going back to using using <cstring> methods that aren't so picky about how you address memory.

              JKSHJ 1 Reply Last reply
              0
              • Kent-DorfmanK Kent-Dorfman

                another fly in the ointment that makes std::copy unsuitable for moving memory buffers around:

                Given the above example of copying the bytes of a uint32_t to an arbitrary memory location, the destPtr (being of type uint8_t*) wont allow std::copy to copy the whole range from the input iteratores. It only copies one byte! Some would argue that destPtr should then be of type uint32_t* but that could cause other problems since there is no guarantee that the destination address would be word aligned...IOW, I don't necessarily want it to be aligned, but instead packed.

                going back to using using <cstring> methods that aren't so picky about how you address memory.

                JKSHJ Offline
                JKSHJ Offline
                JKSH
                Moderators
                wrote on last edited by
                #8

                @Kent-Dorfman You can cast your input pointers to <uint8_t*> (and change your pointer arithmetic for the end iterator) before passing them to std::copy.

                going back to using using <cstring> methods

                I thought that was strongly discouraged?

                Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                1 Reply Last reply
                0
                • Kent-DorfmanK Offline
                  Kent-DorfmanK Offline
                  Kent-Dorfman
                  wrote on last edited by
                  #9

                  I understand why, but std::copy is just too particular about operand types for generic RAM (network buffer) manipulation. Going back to <cstring> methods that use void*...yeah, it violates the consortium rules but this is embedded programming, not high level algorithmic stuff..and rank has its privilege. I'm the one driving the conformance level so nobody is gonna complain if I make their life easier. and in the end, violations just have to be documented, if I leave the rule turned on. at this point I'm inclined to disable that particular rule as being overly strict for nodes with no safety critical functions.

                  1 Reply Last reply
                  0
                  • jeremy_kJ Offline
                    jeremy_kJ Offline
                    jeremy_k
                    wrote on last edited by
                    #10

                    memmove() or memcpy() sound like the right abstraction for a block of memory. std::copy() deals a range of items that may be noncontiguous or have copy constructors. Using it on a buffer presumably means breaking that abstraction to get char sized chunks, while having limited potential to utilize the iterator abstraction. I guess it could make sense with a scatter/gather interface.

                    Asking a question about code? http://eel.is/iso-c++/testcase/

                    1 Reply Last reply
                    1
                    • fcarneyF Offline
                      fcarneyF Offline
                      fcarney
                      wrote on last edited by
                      #11

                      I just don't get where it fails from this discussion:

                      #include <cstdint>
                      #include <algorithm>
                      #include <cassert>
                      
                      int main(int argc, char *argv[])
                      {
                          constexpr size_t length = 0x20U;
                          uint8_t* ptr = new uint8_t[length];
                          for(size_t count=0; count<length; ++count)
                              ptr[count] = count;
                          uint8_t* dest = new uint8_t[length];
                          std::copy(ptr, ptr+length, dest);
                          for(size_t count=0; count<length; ++count){
                              assert(ptr[count] == dest[count]);
                          }
                          delete[] ptr;
                          delete[] dest;
                      
                          return 0;
                      }
                      

                      I tested in both c++11 and c++17.

                      C++ is a perfectly valid school of magic.

                      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