void * или char * для общего представления буфера? - PullRequest
16 голосов
/ 28 сентября 2010

Я разрабатываю класс Buffer, целью которого является представление фрагмента памяти.

Мой базовый буфер - char* (ну, на самом деле boost::shared_array<char>, но это не имеет значения).

Я застрял в решении, какой прототип выбрать для моего конструктора:

Должен ли я пойти с:

Buffer(const void* buf, size_t buflen);

Или с:

Buffer(const char* buf, size_t buflen);

Или что-то еще?

Что обычно делается и почему?

Ответы [ 6 ]

16 голосов
/ 28 сентября 2010

Для конструктора и других функций API преимущество void* заключается в том, что он позволяет вызывающей стороне передавать указатель на любой тип без необходимости выполнять ненужное приведение.Если для вызывающего абонента имеет смысл передавать любой тип, то void* предпочтительнее.Если на самом деле имеет смысл только передать вызывающему абоненту char*, используйте этот тип.

14 голосов
/ 28 сентября 2010

API-интерфейс более понятен для пользователя, если буфер имеет тип void *, а строка имеет тип char *. Сравните определения функций memcpy и strcpy.

10 голосов
/ 28 сентября 2010

C ++ 17

C ++ 17 введено std::byte специально для этого.

Его определение на самом деле просто: enum class byte : unsigned char {};.


Я обычно использовал unsigned char в качестве базовой структуры (не хочу, чтобы подпись портилась с моим буфером, потому что я знаю, по какой причине). Однако я обычно печатал это так:

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

// C++98
typedef unsigned char byte;

А затем обозначьте его как byte*, который, на мой взгляд, четко передает значение, лучше, чем, по крайней мере, char* или void*.

6 голосов
/ 10 мая 2011

Я бы порекомендовал uint8_t, который определен в stdint.h. По сути, это то же самое, что и «typedef unsigned char byte»; что другие рекомендуют, но он имеет преимущество в том, что является частью стандарта C.

Что касается пустоты *, я бы использовал это только для полиморфизма. то есть. Я бы назвал что-то пустым указателем, только если бы я еще не знал, на что он будет указывать. В вашем случае у вас есть массив байтов, поэтому я бы пометил его как таковой, используя тип uint8_t *.

6 голосов
/ 28 сентября 2010

Я бы предпочел char*, потому что лично для меня это лучше, если бы он был "буфером". void* больше похоже на «указатель на то, что я не знаю». Кроме того, в любом случае это то, что лежит в основе.

2 голосов
/ 30 января 2017

Я предпочитаю unsigned char * или uint8_t * для реализации буфера, так как void * имеет раздражающее ограничение, что вы не можете выполнять указатель по математике. Поэтому, если вы хотите обработать некоторые данные с некоторым смещением от буфера, или просто разбить свой буфер на куски или что-то еще, вы все равно прекратите приведение к другому типу для выполнения математических операций.

Я предпочитаю unsigned char * или uint8_t * вместо простого char * из-за специальных правил , касающихся псевдонимов, и char *, которые могут серьезно пессимизировать некоторые циклы, работающие с вашими буферами. 1012 *

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...