Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6693047
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 26, 20262026-05-26T05:56:16+00:00 2026-05-26T05:56:16+00:00

I recently asked a question here on Stack Overflow about how to cast my

  • 0

I recently asked a question here on Stack Overflow about how to cast my data from a 16-bit integer followed by an undetermined amount of void*-cast memory into an std::vector of unsigned chars for the sake of using a socket library known as NetLink which uses a function whose signature looks like this to send raw data:

void rawSend(const vector<unsigned char>* data);

(for reference, here’s that question: Casting an unsigned int + a string to an unsigned char vector)

The question was successfully answered and I’m grateful to those who responded. Mike DeSimone responded with an example of a send_message() function that converts the data into a format that NetLink accepts (an std::vector), which looks like this:

void send_message(NLSocket* socket, uint16_t opcode, const void* rawData, size_t rawDataSize)
{
    vector<unsigned char> buffer;
    buffer.reserve(sizeof(uint16_t) + rawDataSize);
    buffer.push_back(opcode >> 8);
    buffer.push_back(opcode & 0xFF);
    const unsigned char* base(reinterpret_cast<const unsigned char*>(rawData));
    buffer.insert(buffer.end(), base, base + rawDataSize);
    socket->rawSend(&buffer);
}

This looks to be exactly what I needed, and so I set off to write an accompanying receive_message() function…

…but I’m embarrassed to say that I don’t entirely understand all the bit-shifting and whatnot, so I’ve run into a wall here. In all the code I’ve ever written in the past nearly decade, most of my code has been in higher-level languages, and the rest of my code hasn’t ever really called for lower-level memory operations.

Back on the subject of writing a receive_message() function, my starting point, as you might imagine, is NetLink’s rawRead() function, whose signature looks like this:

vector<unsigned char>* rawRead(unsigned bufferSize = DEFAULT_BUFFER_SIZE, string* hostFrom = NULL);

It looks like my code will start off something like this:

void receive_message(NLSocket* socket, uint16_t* opcode, const void** rawData)
{
    std::vector<unsigned char, std::allocator<unsigned char>>* buffer = socket->rawRead();
    std::allocator<unsigned char> allocator = buffer->get_allocator(); // do I even need this allocator?  I saw that one is returned as part of the above object, but...
    // ...
}

After that first call to rawRead(), it appears I would need to iterate through the vector, retrieving data from it and reversing bitshifting operations, and then return the data into *rawData and *opcode. Again, I’m not very familiar with bitshifting (I did some googling to understand the syntax, but I don’t understand why the above send_message() code requires shifting at all), so I’m at a loss for my next step here.

Can someone help me to understand how to write this accompanying receive_message() function? As a bonus, if someone could help explain the original code so that I know for the future how it works (particularly, how the shifting works in this case and why it’s necessary), that would serve to deepen my understanding much for the future.

Thanks in advance!

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-26T05:56:16+00:00Added an answer on May 26, 2026 at 5:56 am

    The library’s function signature …

        void rawSend( const vector<unsigned char>* data );
    

    forces you to build a std::vector of your data, which in essence means that it imposes a needless inefficiency. There is no advantage in requiring client code to build a std::vector. Whoever designed that do not know what they’re doing, and it would be wise to not use their software.

    The library function signature …

        vector<unsigned char>* rawRead(unsigned bufferSize = DEFAULT_BUFFER_SIZE, string* hostFrom = NULL);
    

    is worse: it not just needlessly requires you to build a std::string if you want to specify a “hostFrom” (whatever that really means), but it needlessly requires you to deallocate the result vector. At least if there is any sense to function result type. Which, of course, there might not be.

    You should not be using a library with so disgusting function signatures. Probably any randomly picked library will be much better. I.e., much easier to use.


    How the existing usage code …

    void send_message(NLSocket* socket, uint16_t opcode, const void* rawData, size_t rawDataSize)
    {
        vector<unsigned char> buffer;
        buffer.reserve(sizeof(uint16_t) + rawDataSize);
        buffer.push_back(opcode >> 8);
        buffer.push_back(opcode & 0xFF);
        const unsigned char* base(reinterpret_cast<const unsigned char*>(rawData));
        buffer.insert(buffer.end(), base, base + rawDataSize);
        socket->rawSend(&buffer);
    }
    

    works:

    • The reserve call is a case of premature optimization. It tries to make the vector do just one single buffer allocation (performed at this point) instead of possibly two or more. A much better cure for the manifest inefficiency of building a vector, is to use a more sane library.

    • The buffer.push_back(opcode >> 8) places the high 8 bits of (assumed) 16-bit quantity opcode, at the start of the vector. Placing the high part, the most significant part, first, is known as big endian format. Your reading code at the other end must assume big endian format. And likewise, if this sending code had use little endian format, then the reading code would have to assume little endian format. So, this is just a data format decision, but given the decision the code at both ends must adhere to it.

    • The buffer.push_back(opcode & 0xFF) calls places the low 8 bits of opcode after the high bits, as is correct for big endian.

    • The const unsigned char* base(reinterpret_cast<const unsigned char*>(rawData)) declaration just names a suitably typed pointer to your data, calling it base. The type const unsigned char* is suitable because it allows byte level address arithmetic. The original formal argument type const void* does not admit address arithmetic.

    • The buffer.insert(buffer.end(), base, base + rawDataSize) adds the data to the vector. The expression base + rawDataSize is the address arithmetic that the previous declaration enabled.

    • socket->rawSend(&buffer) is the final call down to the SillyLibrary’s rawSend method.


    How to wrap a call to the SillyLibrary rawRead function.

    First, define a name for the byte datatype (always a good idea to name things):

    typedef unsigned char Byte;
    typedef ptrdiff_t Size;
    

    Consult the documentation about how to deallocate/destroy/delete (if necessary) the SillyLibrary function result:

    void deleteSillyLibVector( vector<Byte> const* p )
    {
        // perhaps just "delete p", but it depends on the SillyLibrary
    }
    

    Now, for the send operation having std::vector involved was just a pain. For the receive operation, it’s opposite. Creating a dynamic array and passing it safely and efficiently as a function result, is just the kind of thing that std::vector was designed for.

    However, the send operation was just a single call.

    For the receive operation it is possible, depending on the design of SillyLibrary, the you need to loop, to perform of number of receive calls until you have received all the data. You do not provide enough information to do this. But the code below shows a bottom layer read that your looping code can call, accumulating data in a vector:

    Size receive_append( NLSocket& socket, vector<Byte>& data )
    {
        vector<Byte> const* const result = socket.raw_read();
    
        if( result == 0 )
        {
            return 0;
        }
    
        struct ScopeGuard
        {
            vector<Byte>* pDoomed;
            explicit ScopeGuard( vector<Byte>* p ): pDoomed( p ) {}
            ~ScopeGuard() { deleteSillyLibVector( pDoomed ); }
        };
    
        Size const nBytesRead = result->size();
        ScopeGuard cleanup( result );
    
        data.insert( data.end(), result->begin(), result->end() );
        return nBytesRead;
    }
    

    Note the use of a destructor to do cleanup, which makes this more exception safe. In this particular case about the only possible exception is a std::bad_alloc, which is pretty fatal anyway. But the general technique of using a destructor to do cleanup, for exception safety, is very much worth knowing about and using as a matter of course (usually one does not have to define any new class, though, but when dealing with a SillyLibrary one may have to do that).

    Finally, when your looping code has determined that all data is at hand, it can interpret the data in your vector. I leave that as an exercise, even though that is mainly what you asked for. And that is because I have already written almost like a whole article here.

    Disclaimer: off-the-cuff code.

    Cheers & hth.,

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I've recently asked a question regarding best ways of separating business logic from data
OK, so this is leading on from another question I asked here recently. Basically,
I recently asked a question about LAMP stack not allowing posting of <script> tag
I asked a question [ here ] recently and it's just not providing me
Here one more basic question asked in MS interview recently class A { public
I recently asked a question about IIf vs. If and found out that there
I recently asked a question about what I called method calls. The answer referred
I recently asked a question about Oracle Encryption. Along the way to finding a
I recently asked a question about tracing Linq-to-Entities I think that one of the
I recently asked a question about functional programming, and received (good!) answers that prompted

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.