C++ 的最佳 C 实现是什么?向量?

发布于 2024-12-11 00:37:46 字数 136 浏览 0 评论 0原文

我一直在考虑使用 C 而不是 C++,因为我发现它更干净,而且我发现它主要缺少的是像数组这样的向量。

最好的实现是什么?

我希望能够调用诸如 vector_create、vector_at、vector_add 等之类的东西。

I've been looking into using C over C++ as I find it cleaner and the main thing I find it to lack is a vector like array.

What is the best implementation of this?

I want to just be able to call something like vector_create, vector_at, vector_add, etc.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

萌逼全场 2024-12-18 00:37:47

如果你可以乘法,那么当你有 malloc() 甚至 calloc() 时,真的不需要 vector_create() 函数。您只需跟踪两个值,即指针和分配的大小,并将两个值而不是一个值发送到您将“向量”传递给的任何函数(如果该函数实际上需要指针和大小,也就是说) 。 malloc() 保证内存块可作为任何类型寻址,因此将其 void * 返回值分配给例如 struct car * 并使用 [] 对其进行索引。大多数处理器访问array[index]几乎与variable一样快,而vector_at()函数可能慢很多倍。如果将指针和大小一起存储在结构中,则只能在非时间关键代码中执行此操作,否则必须使用 vector.ptr[index] 进行索引。使用 free() 删除空间。

专注于围绕 realloc() 编写一个好的包装器,它仅在例如 2 或 1.5 的每个幂上重新分配。请参阅 user786653 的维基百科链接

当然,如果内存耗尽,calloc()、malloc() 和 realloc() 可能会失败,这是需要向量类型的另一个可能原因。 C++ 有异常,如果你没有捕获它,它会自动终止程序,而 C 则没有。但这是另一个讨论了。

If you can multiply, there's really no need for a vector_create() function when you have malloc() or even calloc(). You just have to keep track of two values, the pointer and the allocated size, and send two values instead of one to whatever function you pass the "vector" to (if the function actually needs both the pointer and the size, that is). malloc() guarantees that the memory chunk is addressable as any type, so assign it's void * return value to e.g. a struct car * and index it with []. Most processors access array[index] almost as fast as variable, while a vector_at() function can be many times slower. If you store the pointer and size together in a struct, only do it in non time-critical code, or you'll have to index with vector.ptr[index]. Delete the space with free().

Focus on writing a good wrapper around realloc() instead, that only reallocates on every power of e.g. 2 or 1.5. See user786653's Wikipedia link.

Of course, calloc(), malloc() and realloc() can fail if you run out memory, and that's another possible reason for wanting a vector type. C++ has exceptions that automatically terminate the program if you don't catch it, C doesn't. But that's another discussion.

小女人ら 2024-12-18 00:37:47

C 中缺乏模板功能使得不可能支持类似向量的结构。您能做的最好的事情就是在预处理器的帮助下定义一个“通用”结构,然后为您想要支持的每种类型进行“实例化”。

Lack of template functionality in C makes it impossible to support a vector like structure. The best you can do is to define a 'generic' structure with some help of the preprocessor, and then 'instantiate' for each of the types you want to support.

错々过的事 2024-12-18 00:37:46

编辑

这个答案来自一百万年前,但在某个时候,我实际上在 C 中实现了一个基于宏的、高效的、类型安全的向量,它涵盖了所有典型的功能和需求。您可以在这里找到它:

https://github.com/eteran/c-vector

回答如下。


您想要复制的载体怎么样?我的意思是最后,这一切都归结为这样的事情:

int *create_vector(size_t n) {
    return malloc(n * sizeof(int));
}

void delete_vector(int *v) {
    free(v);
}

int *resize_vector(int *v, size_t n) {
    return realloc(v, n * sizeof(int));
    /* returns NULL on failure here */
}

您可以将这一切包装在一个结构中,因此它也“知道它的大小”,但您必须为每种类型执行此操作(这里是宏?) ,但这似乎有点不必要......也许是这样的:

typedef struct {
    size_t size;
    int *data;
} int_vector;

int_vector *create_vector(size_t n) {
    int_vector *p = malloc(sizeof(int_vector));
    if(p) {
        p->data = malloc(n * sizeof(int));
        p->size = n;
    }
    return p;
}

void delete_vector(int_vector *v) {
    if(v) {
        free(v->data);
        free(v);
    }
}

size_t resize_vector(int_vector *v, size_t n) {
    if(v) {
        int *p = realloc(v->data, n * sizeof(int));
        if(p) {
            v->data = p;
            v->size = n;
        }
        return v->size;
    }
    return 0;
}

int get_vector(int_vector *v, size_t n) {
    if(v && n < v->size) {
        return v->data[n];
    }
    /* return some error value, i'm doing -1 here, 
     * std::vector would throw an exception if using at() 
     * or have UB if using [] */
    return -1;
}

void set_vector(int_vector *v, size_t n, int x) {
    if(v) {
        if(n >= v->size) {
            resize_vector(v, n);
        }
        v->data[n] = x;
    }
}

之后,你可以这样做:

int_vector *v = create_vector(10);
set_vector(v, 0, 123);

我不知道,这似乎不值得付出努力。

EDIT

This answer is from a million years ago, but at some point, I actually implemented a macro-based, efficient, type-safe vector work-alike in C that covers all the typical features and needs. You can find it here:

https://github.com/eteran/c-vector

Original answer below.


What about a vector are you looking to replicate? I mean in the end, it all boils down to something like this:

int *create_vector(size_t n) {
    return malloc(n * sizeof(int));
}

void delete_vector(int *v) {
    free(v);
}

int *resize_vector(int *v, size_t n) {
    return realloc(v, n * sizeof(int));
    /* returns NULL on failure here */
}

You could wrap this all up in a struct, so it "knows its size" too, but you'd have to do it for every type (macros here?), but that seems a little uneccessary... Perhaps something like this:

typedef struct {
    size_t size;
    int *data;
} int_vector;

int_vector *create_vector(size_t n) {
    int_vector *p = malloc(sizeof(int_vector));
    if(p) {
        p->data = malloc(n * sizeof(int));
        p->size = n;
    }
    return p;
}

void delete_vector(int_vector *v) {
    if(v) {
        free(v->data);
        free(v);
    }
}

size_t resize_vector(int_vector *v, size_t n) {
    if(v) {
        int *p = realloc(v->data, n * sizeof(int));
        if(p) {
            v->data = p;
            v->size = n;
        }
        return v->size;
    }
    return 0;
}

int get_vector(int_vector *v, size_t n) {
    if(v && n < v->size) {
        return v->data[n];
    }
    /* return some error value, i'm doing -1 here, 
     * std::vector would throw an exception if using at() 
     * or have UB if using [] */
    return -1;
}

void set_vector(int_vector *v, size_t n, int x) {
    if(v) {
        if(n >= v->size) {
            resize_vector(v, n);
        }
        v->data[n] = x;
    }
}

After which, you could do:

int_vector *v = create_vector(10);
set_vector(v, 0, 123);

I dunno, it just doesn't seem worth the effort.

离笑几人歌 2024-12-18 00:37:46

据我所知,在 C 语言中创建一套全面的实用程序类型的最完整的工作是 GLib< /a>.为了满足您的特定需求,它提供了 g_array_newg_array_append_val 等。请参阅 GLib 数组文档

The most complete effort I know of to create a comprehensive set of utility types in C is GLib. For your specific needs it provides g_array_new, g_array_append_val and so on. See GLib Array Documentation.

情定在深秋 2024-12-18 00:37:46

而不是在 @EvanTeran 的回答 我想我应该在这里提交更长的回复。

正如各种评论所暗示的那样,尝试复制 std::vector 的确切行为实际上没有多大意义,因为 C 缺乏模板并且 RAII

然而,有用的是仅适用于字节的 动态数组 实现。显然,这可以直接用于 char* 字符串,但也可以轻松适应任何其他类型,只要您小心地将 size 参数乘以 sizeof(the_type)

Rather than going off on a tangent in the comments to @EvanTeran's answer I figured I'd submit a longer reply here.

As various comments allude to there's really not much point in trying to replicate the exact behavior of std::vector since C lacks templates and RAII.

What can however be useful is a dynamic array implementation that just works with bytes. This can obviously be used directly for char* strings, but can also easily be adapted for usage with any other types as long as you're careful to multiply the size parameter by sizeof(the_type).

感情洁癖 2024-12-18 00:37:46

Apache Portable Runtime 有一套不错的 数组函数 并且全部是 C。

请参阅 教程 进行快速介绍。

Apache Portable Runtime has a decent set of array functions and is all C.

See the tutorial for a quick intro.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文