简体   繁体   中英

void* or char* for generic buffer representation?

I'm designing a Buffer class whose purpose is to represent a chunk of memory.

My underlying buffer is a char* (well, a boost::shared_array<char> actually, but it doesn't really matter).

I'm stuck at deciding what prototype to choose for my constructor:

Should I go with:

Buffer(const void* buf, size_t buflen);

Or with:

Buffer(const char* buf, size_t buflen);

Or something else ?

What is usually done, and why ?

For the constructor and other API functions, the advantage of void* is that it allows the caller to pass in a pointer to any type without having to do an unnecessary cast. If it makes sense for the caller to be able to pass in any type, then void* is preferable. If it really only makes sense for the caller to be able to pass in char* , then use that type.

API interface is more clear for user, if buffer has void* type, and string has char* type. Compare memcpy and strcpy function definitions.

C++17

C++17 introduced std::byte specifically for this.

Its definition is actually simple: enum class byte : unsigned char {}; .


I generally used unsigned char as the underlying structure (don't want signedness to mess up with my buffer for I know what reason). However I usually typedefed it:

// C++11
using byte = unsigned char;

// C++98
typedef unsigned char byte;

And then refer to it as byte* which neatly conveys the meaning in my opinion, better than either char* or void* at least.

I'd prefer char* , because for me personally it plays better with being "a buffer". void* seems more like "a pointer to I don't know what". Besides, it is what your underlying is, anyway.

I'd recommend uint8_t, which is defined in stdint.h. It's basically the same thing as the "typedef unsigned char byte;" that others have been recommending, but it has the advantage of being part of the C standard.

As for void*, I would only use that for polymorphism. ie. I'd only call something a void pointer if I didn't yet know what type of thing it would be pointing to. In your case you've got an array of bytes, so I'd label it as such by using uint8_t* as the type.

I prefer unsigned char * or uint8_t * for buffer implementations, since void * has the annoying restriction that you can't perform pointer math on it. So if you want to process some data at some offset from the buffer, or just break your buffer up into chunks or whatever, you are stuck casting to some other type anyway to do the math.

I prefer unsigned char * or uint8_t * over plain char * because of the special rules regarding aliasing and char * , which has the potential to seriously pessimize some loops working on your buffers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM