我正在设计一个Buffer类,其目的是代表一块内存。
我的底层缓冲区是char*
(实际上是boost::shared_array<char>
,但实际上并不重要。)
我一直在决定为我的构造函数选择什么样的原型:
我应该选择:
Buffer(const void* buf, size_t buflen);
或者用:
Buffer(const char* buf, size_t buflen);
还是其他什么?
通常做什么,为什么?
答案 0 :(得分:16)
对于构造函数和其他API函数,void*
的优点是它允许调用者将指针传递给任何类型而无需进行不必要的强制转换。如果调用者能够传入任何类型是有意义的,那么void*
更可取。如果调用者能够传入char*
真的有意义,那么请使用该类型。
答案 1 :(得分:13)
如果缓冲区具有void *类型,并且string具有char *类型,则API接口对用户更清晰。比较memcpy和strcpy函数定义。
答案 2 :(得分:9)
<强> 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*
更好。
答案 3 :(得分:6)
我更喜欢char*
,因为对我而言,它更适合作为“缓冲区”。 void*
似乎更像是“指向我不知道的东西”。此外,无论如何,这都是你的基础。
答案 4 :(得分:6)
我建议使用uint8_t,它在stdint.h中定义。它与“typedef unsigned char byte”基本相同;其他人一直在推荐,但它具有成为C标准一部分的优势。
至于void *,我只会将其用于多态。即。如果我还不知道它会指向什么类型的东西,我只会调用一些无效指针。在你的情况下你有一个字节数组,所以我通过使用uint8_t *作为类型来标记它。
答案 5 :(得分:2)
我更喜欢pkg-config --cflags gtk+-3.0 --libs gtk+-3.0
或#include <gtk/gtk.h>
gboolean draw_callback (GtkWidget *widget, cairo_t *cr, gpointer data)
{
guint width, height;
GdkRGBA color;
GtkStyleContext *context;
context = gtk_widget_get_style_context (widget);
width = gtk_widget_get_allocated_width (widget);
height = gtk_widget_get_allocated_height (widget);
gtk_render_background(context, cr, 0, 0, width, height);
cairo_arc (cr, width/2.0, height/2.0, MIN (width, height) / 2.0, 0, 2 * G_PI);
gtk_style_context_get_color (context, gtk_style_context_get_state (context), &color);
gdk_cairo_set_source_rgba (cr, &color);
gdk_cairo_set_source_rgba (cr, &color);
cairo_fill (cr);
return FALSE;
}
gint main(int argc,char *argv[])
{
GtkWidget *window, *drawing_area;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
drawing_area = gtk_drawing_area_new();
gtk_container_add (GTK_CONTAINER (window), drawing_area);
gtk_widget_set_size_request (drawing_area, 200, 100);
g_signal_connect (G_OBJECT (drawing_area), "draw", G_CALLBACK (draw_callback), NULL);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
缓冲区实现,因为unsigned char *
有一个烦人的限制,你无法对其执行指针数学运算。因此,如果你想处理一些偏离缓冲区的数据,或者只是将你的缓冲区分成块或其他任何东西,你就会被迫投射到其他类型来进行数学运算。
我更喜欢uint8_t *
或void *
优于普通unsigned char *
,因为special rules有关别名和uint8_t *
,这有可能严重地使一些循环工作变得悲观在缓冲区上。