Void * или char * для представления общего буфера?

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

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

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

Должен ли я идти с:

Buffer(const void* buf, size_t buflen);

Или с помощью:

Buffer(const char* buf, size_t buflen);

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

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

Ответ 1

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

Ответ 2

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

Ответ 3

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

typedef unsigned char byte;

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

Ответ 4

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

Ответ 5

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

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

Ответ 6

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

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