- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个简单的结构来保存一个数组:
struct array_of_a_type {
size_t allocated_size;
size_t elements; /* 1-index based */
a_type *array;
};
我想写一个简单的函数,像这样:
bool simple_function(struct array_of_a_type *my_array, int a, int b, int c, int d)
{
a_type new_chunk[] = {
a, b, a+b, d, c,
c, c, c+d, b+d, a,
a+c, b+c, c+d, c+d, c,
};
size_t size = sizeof(new_chunk) / sizeof(a_type);
return push_to_array(my_array, new_chunk, size);
}
my_array 是一个静态的全局变量。下面是 push_to_array 的实现。
static bool push_to_array(struct array_of_a_type *a, a_type *new_chunk, size_t size)
{
const size_t new_size = a->elements + size;
const size_t old_size = a->elements;
if (new_size > a->allocated_size) {
/* The allocated_size is most of the time big enough.
I’ve stripped this part of code to minimum. */
a_type *tmp = realloc(a->array, new_size * sizeof(a_type));
if (!tmp) {
return true;
} else {
a->array = tmp;
a->allocated_size = new_size;
}
}
a->elements = new_size;
memcpy(a->array + old_size, new_chunk, size * sizeof(a_type));
return false;
}
我的问题:
我如何重写“simple_function”以使更多编译器生成将直接写入目标的代码?我希望代码保持简短和灵活。
我的代码有效。不幸的是,gcc(和旧的 clang)在堆栈上创建临时数据,然后将其复制到目的地。下面是生成的 x86_64 汇编程序的片段。
movq 8(%rsp), %rdx
movq %rdx, 8(%rax)
movq 16(%rsp), %rdx
movq %rdx, 16(%rax)
movq 24(%rsp), %rdx
movq %rdx, 24(%rax)
movq 32(%rsp), %rdx
movq %rdx, 32(%rax)
对于 AMD,汇编器有这个:
rep movsq
新的 clang 工作正常。我用 -O3 编译。
我试过一次添加一个元素的代码。不幸的是,有很多条件跳转调用 realloc。
最佳答案
为了提高效率,您需要分离增长数组的逻辑,并将值分配给(未使用的)槽,以避免额外的副本(从堆栈到数组)。
为了美化代码,您可以创建一组辅助宏。我假设“推”是指“附加到数组”。如果您的意思真的是“前置”,那么还需要一个额外的 memmove()
。
假设你有
#include <stdlib.h>
#include <stdio.h>
typedef int array_data_type;
typedef struct {
size_t size;
size_t used;
array_data_type *item;
} array_type;
#define ARRAY_INITIALIZER { 0, 0, NULL }
void array_free(array_type *const array)
{
free(array->item);
array->size = 0;
array->used = 0;
array->item = NULL;
}
void array_init(array_type *const array)
{
array->size = 0;
array->used = 0;
array->item = NULL;
}
void array_init_size(array_type *const array, const size_t size)
{
if (!size) {
array->size = 0;
array->used = 0;
array->item = NULL;
return;
}
array->item = malloc(size * sizeof array->item[0]);
if (!array->item) {
fprintf(stderr, "array_init_size(%p, %zu): Out of memory.\n", (void *)array, size);
exit(EXIT_FAILURE);
}
array->size = size;
array->used = 0;
}
void array_grow_to(array_type *const array, size_t size)
{
array_data_type *temp;
if (size < 4)
size = 4;
else
if (size < 16777216) {
size |= size >> 1;
size |= size >> 2;
size |= size >> 4;
size |= size >> 8;
size |= size >> 16;
size++;
} else
size = (size | 8388607) + 8388609;
temp = realloc(array->item, size * sizeof array->item[0]);
if (!temp) {
fprintf(stderr, "array_grow_to(%p, %zu): Out of memory.\n", (void *)array, size);
exit(EXIT_FAILURE);
}
array->item = temp;
array->size = size;
}
static inline array_data_type *array_grow_by(array_type *const array, size_t const count)
{
array_data_type *retval;
if (array->used + count > array->size)
array_grow_to(array, array->used + count);
retval = array->item + array->used;
array->used += count;
return retval;
}
我喜欢使用 used
表示数组中的元素数量,使用 size
表示数组已分配内存的元素数量。如果您习惯了其他名称,请搜索并替换。
array_grow_to()
将新大小至少调整为 4,如果小于 16,777,216,则调整为 2 的下一个幂,或者调整为 8,388,608 的更大倍数。这限制了为非常大的列表分配但未使用的内存量。
array_grow_by()
确保数组有空间容纳 count
个新元素,并返回指向第一个新的未使用元素的指针。
如果定义以下 C99 预处理器宏,
#define MACRO_CONCATENATE(part1, ...) part1 ## __VA_ARGS__
#define ARRAY_SET_N(array, count, ...) MACRO_CONCATENATE(ARRAY_SET_, count)(array, count, __VA_ARGS__)
#define ARRAY_SET_0(...)
#define ARRAY_SET_1(a, n, v) a[n-1] = v
#define ARRAY_SET_2(a, n, v, ...) a[n-2] = v; ARRAY_SET_1(a, n, __VA_ARGS__)
#define ARRAY_SET_3(a, n, v, ...) a[n-3] = v; ARRAY_SET_2(a, n, __VA_ARGS__)
#define ARRAY_SET_4(a, n, v, ...) a[n-4] = v; ARRAY_SET_3(a, n, __VA_ARGS__)
#define ARRAY_SET_5(a, n, v, ...) a[n-5] = v; ARRAY_SET_4(a, n, __VA_ARGS__)
#define ARRAY_SET_6(a, n, v, ...) a[n-6] = v; ARRAY_SET_5(a, n, __VA_ARGS__)
#define ARRAY_SET_7(a, n, v, ...) a[n-7] = v; ARRAY_SET_6(a, n, __VA_ARGS__)
#define ARRAY_SET_8(a, n, v, ...) a[n-8] = v; ARRAY_SET_7(a, n, __VA_ARGS__)
#define ARRAY_SET_9(a, n, v, ...) a[n-9] = v; ARRAY_SET_8(a, n, __VA_ARGS__)
#define ARRAY_SET_10(a, n, v, ...) a[n-10] = v; ARRAY_SET_9(a, n, __VA_ARGS__)
#define ARRAY_SET_11(a, n, v, ...) a[n-11] = v; ARRAY_SET_10(a, n, __VA_ARGS__)
#define ARRAY_SET_12(a, n, v, ...) a[n-12] = v; ARRAY_SET_11(a, n, __VA_ARGS__)
#define ARRAY_SET_13(a, n, v, ...) a[n-13] = v; ARRAY_SET_12(a, n, __VA_ARGS__)
#define ARRAY_SET_14(a, n, v, ...) a[n-14] = v; ARRAY_SET_13(a, n, __VA_ARGS__)
#define ARRAY_SET_15(a, n, v, ...) a[n-15] = v; ARRAY_SET_14(a, n, __VA_ARGS__)
#define ARRAY_SET_16(a, n, v, ...) a[n-16] = v; ARRAY_SET_15(a, n, __VA_ARGS__)
#define ARRAY_SET_17(a, n, v, ...) a[n-17] = v; ARRAY_SET_16(a, n, __VA_ARGS__)
#define ARRAY_SET_18(a, n, v, ...) a[n-18] = v; ARRAY_SET_17(a, n, __VA_ARGS__)
#define ARRAY_SET_19(a, n, v, ...) a[n-19] = v; ARRAY_SET_18(a, n, __VA_ARGS__)
#define ARRAY_SET_20(a, n, v, ...) a[n-20] = v; ARRAY_SET_19(a, n, __VA_ARGS__)
#define ARRAY_SET_21(a, n, v, ...) a[n-21] = v; ARRAY_SET_20(a, n, __VA_ARGS__)
#define ARRAY_SET_22(a, n, v, ...) a[n-22] = v; ARRAY_SET_21(a, n, __VA_ARGS__)
#define ARRAY_SET_23(a, n, v, ...) a[n-23] = v; ARRAY_SET_22(a, n, __VA_ARGS__)
#define ARRAY_SET_24(a, n, v, ...) a[n-24] = v; ARRAY_SET_23(a, n, __VA_ARGS__)
#define ARRAY_SET_25(a, n, v, ...) a[n-25] = v; ARRAY_SET_24(a, n, __VA_ARGS__)
#define ARRAY_SET_26(a, n, v, ...) a[n-26] = v; ARRAY_SET_25(a, n, __VA_ARGS__)
#define ARRAY_SET_27(a, n, v, ...) a[n-27] = v; ARRAY_SET_26(a, n, __VA_ARGS__)
#define ARRAY_SET_28(a, n, v, ...) a[n-28] = v; ARRAY_SET_27(a, n, __VA_ARGS__)
#define ARRAY_SET_29(a, n, v, ...) a[n-29] = v; ARRAY_SET_28(a, n, __VA_ARGS__)
#define ARRAY_SET_30(a, n, v, ...) a[n-30] = v; ARRAY_SET_29(a, n, __VA_ARGS__)
#define ARRAY_SET_31(a, n, v, ...) a[n-31] = v; ARRAY_SET_30(a, n, __VA_ARGS__)
#define ARRAY_SET_32(a, n, v, ...) a[n-32] = v; ARRAY_SET_31(a, n, __VA_ARGS__)
#define ARRAY_SET_33(a, n, v, ...) a[n-33] = v; ARRAY_SET_32(a, n, __VA_ARGS__)
#define ARRAY_SET_34(a, n, v, ...) a[n-34] = v; ARRAY_SET_33(a, n, __VA_ARGS__)
#define ARRAY_SET_35(a, n, v, ...) a[n-35] = v; ARRAY_SET_34(a, n, __VA_ARGS__)
#define ARRAY_SET_36(a, n, v, ...) a[n-36] = v; ARRAY_SET_35(a, n, __VA_ARGS__)
#define ARRAY_SET_37(a, n, v, ...) a[n-37] = v; ARRAY_SET_36(a, n, __VA_ARGS__)
#define ARRAY_SET_38(a, n, v, ...) a[n-38] = v; ARRAY_SET_37(a, n, __VA_ARGS__)
#define ARRAY_SET_39(a, n, v, ...) a[n-39] = v; ARRAY_SET_38(a, n, __VA_ARGS__)
#define ARRAY_SET_40(a, n, v, ...) a[n-40] = v; ARRAY_SET_39(a, n, __VA_ARGS__)
#define ARRAY_SET_41(a, n, v, ...) a[n-41] = v; ARRAY_SET_40(a, n, __VA_ARGS__)
#define ARRAY_SET_42(a, n, v, ...) a[n-42] = v; ARRAY_SET_41(a, n, __VA_ARGS__)
#define ARRAY_SET_43(a, n, v, ...) a[n-43] = v; ARRAY_SET_42(a, n, __VA_ARGS__)
#define ARRAY_SET_44(a, n, v, ...) a[n-44] = v; ARRAY_SET_43(a, n, __VA_ARGS__)
#define ARRAY_SET_45(a, n, v, ...) a[n-45] = v; ARRAY_SET_44(a, n, __VA_ARGS__)
#define ARRAY_SET_46(a, n, v, ...) a[n-46] = v; ARRAY_SET_45(a, n, __VA_ARGS__)
#define ARRAY_SET_47(a, n, v, ...) a[n-47] = v; ARRAY_SET_46(a, n, __VA_ARGS__)
#define ARRAY_SET_48(a, n, v, ...) a[n-48] = v; ARRAY_SET_47(a, n, __VA_ARGS__)
#define ARRAY_SET_49(a, n, v, ...) a[n-49] = v; ARRAY_SET_48(a, n, __VA_ARGS__)
#define ARRAY_SET_50(a, n, v, ...) a[n-50] = v; ARRAY_SET_49(a, n, __VA_ARGS__)
#define ARRAY_SET_51(a, n, v, ...) a[n-51] = v; ARRAY_SET_50(a, n, __VA_ARGS__)
#define ARRAY_SET_52(a, n, v, ...) a[n-52] = v; ARRAY_SET_51(a, n, __VA_ARGS__)
#define ARRAY_SET_53(a, n, v, ...) a[n-53] = v; ARRAY_SET_52(a, n, __VA_ARGS__)
#define ARRAY_SET_54(a, n, v, ...) a[n-54] = v; ARRAY_SET_53(a, n, __VA_ARGS__)
#define ARRAY_SET_55(a, n, v, ...) a[n-55] = v; ARRAY_SET_54(a, n, __VA_ARGS__)
#define ARRAY_SET_56(a, n, v, ...) a[n-56] = v; ARRAY_SET_55(a, n, __VA_ARGS__)
#define ARRAY_SET_57(a, n, v, ...) a[n-57] = v; ARRAY_SET_56(a, n, __VA_ARGS__)
#define ARRAY_SET_58(a, n, v, ...) a[n-58] = v; ARRAY_SET_57(a, n, __VA_ARGS__)
#define ARRAY_SET_59(a, n, v, ...) a[n-59] = v; ARRAY_SET_58(a, n, __VA_ARGS__)
#define ARRAY_SET_60(a, n, v, ...) a[n-60] = v; ARRAY_SET_59(a, n, __VA_ARGS__)
#define ARRAY_SET_61(a, n, v, ...) a[n-61] = v; ARRAY_SET_60(a, n, __VA_ARGS__)
#define ARRAY_SET_62(a, n, v, ...) a[n-62] = v; ARRAY_SET_61(a, n, __VA_ARGS__)
#define ARRAY_SET_63(a, n, v, ...) a[n-63] = v; ARRAY_SET_62(a, n, __VA_ARGS__)
#define ARRAY_SET_64(a, n, v, ...) a[n-64] = v; ARRAY_SET_63(a, n, __VA_ARGS__)
#define ARRAY_APPEND_N(array, count, ...) \
do { \
array_data_type *const _base = array_grow_by(array, count); \
ARRAY_SET_N(_base, count, __VA_ARGS__); \
} while(0)
然后你可以把你的简单函数写成
void simple_function(array_type *array,
const array_data_type a, const array_data_type b,
const array_data_type c, const array_data_type d)
{
ARRAY_APPEND_N(array, 15, a, b, a+b, d, c,
c, c, c+d, b+d, a,
a+c, b+c, c+d, c+d, c);
}
并将其预处理成(缩进除外)
void simple_function(array_type *array,
const array_data_type a, const array_data_type b,
const array_data_type c, const array_data_type d)
{
do {
array_data_type *const _base = array_grow_by(array, 15);
_base[15 - 15] = a;
_base[15 - 14] = b;
_base[15 - 13] = a+b;
_base[15 - 12] = d;
_base[15 - 11] = c;
_base[15 - 10] = c;
_base[15 - 9] = c;
_base[15 - 8] = c+d;
_base[15 - 7] = b+d;
_base[15 - 6] = a;
_base[15 - 5] = a+c;
_base[15 - 4] = b+c;
_base[15 - 3] = c+d;
_base[15 - 2] = c+d;
_base[15 - 1] = c;
} while(0);
}
通常可以在 Intel/AMD64 架构(以及其他支持相对寻址模式的架构)上编译成出色的机器代码。在其他一些架构上,最好不要让 _base
成为常量,而是自动增加它 (*(_base++) = v;
)。
如果你实现一个PP_NARG()
宏来计算宏参数的数量,你可以添加宏
#define ARRAY_APPEND(array, ...) ARRAY_APPEND_N(array, PP_NARG(__VA_ARGS__), __VA_ARGS__)
在这种情况下你的函数简化为
void simple_function(array_type *array,
const array_data_type a, const array_data_type b,
const array_data_type c, const array_data_type d)
{
ARRAY_APPEND(array, a, b, a+b, d, c,
c, c, c+d, b+d, a,
a+c, b+c, c+d, c+d, c);
}
在某些编译器中预处理器宏参数的数量被限制为 64 个,这将单个宏可以添加的元素的最大数量限制为 62 个。根据您使用的编译器,您可以扩展宏以支持更大数量的参数,但其他编译器可能会因此而窒息。
关于C - 实现将许多元素快速推送到数组末尾,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29725670/
我正在更改链接网址以添加 www.site.com/index.html?s=234&dc=65828 我通过此代码得到的是:site.com/&dc=65828 var target="&dc=65
我在编译过程中收到错误: src/smtp.c:208:1: warning: control reaches end of non-void function [-Wreturn-type] 这是相
这是我的 bootstrap/html 代码: Put email 位置正确,但我希望输入字段的大小延伸到 div 末尾。谁能帮帮我? 最佳答案 只需按百分比指定宽度,如下所示
我正在尝试获取一个像这样的 json 对象: filters = {"filters": myArray}; 并将其附加到 URL 的末尾,使用: this.router.navigate([`/de
这个问题已经有答案了: Remove hash from url (5 个回答) 已关闭 10 年前。 我有一个网站,stepaheadresidents.com ,并且井号 (#) 会自动添加到 u
我有这个代码 $('container a').appendTo('.container'); dzedzdqdqdqzdqdzqdzqdqzdqd Forgot password
为了练习更多 Python 知识,我尝试了 pythonchallenge.com 上的挑战 简而言之,作为第一步,此挑战要求从末尾带有数字的 url 加载 html 页面。该页面包含一行文本,其中有
我对 FS2 很陌生,需要一些有关设计的帮助。我正在尝试设计一个流,它将从底层的 InputStream 中提取 block ,直到结束。这是我尝试过的: import java.io.{File,
我对 FS2 很陌生,需要一些有关设计的帮助。我正在尝试设计一个流,它将从底层的 InputStream 中提取 block ,直到结束。这是我尝试过的: import java.io.{File,
我正在编写一个 ajax 应用程序,并且在 php 脚本中有一个函数: public function expire_user() { $r=array("return"=>'OK');
我正在使用一个QListView,它包装了一个非常简单的列表模型。我想尝试实现类似于某些网页中看到的“无限滚动”的东西。 目前,模型通过最多添加 100 个项目的方法更新(它们取自外部 Web API
运行 cucumber 测试给我以下错误 end of file reached (EOFError) /usr/lib64/ruby/2.0.0/net/protocol.rb:153:in
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我想知道版本命名的具体作用是什么? 喜欢 jquery.js?ver=1.4.4 我的意思是如果我使用像这样的 cdn jquery/1.4.4/jquery.min.js?ver=1.4.4但是另一
" data-fancybox-group="gallery" title="">" alt="" /> 在此代码中 echo $prod['item_image_url'];打印存储在我的表中的图像
我目前使用 Wordpress 作为博客平台,但我想更改为使用 Jekyll 来生成静态页面。在 WordPress 上,我的 URL 使用以下格式: /年/月/日/标题 但我想将其重定向到 /年/月
根据docs这应该是不可能的 Regular expressions cannot be anchored to the beginning or end of a token 尽管如此,它似乎对我有
有没有办法创建 dijit 并将其附加到 div 的末尾?假设我有以下代码: Add Person 我在网上找到了以下代码,但这替换了我的“attendants”div: var personCo
我有这段代码: //execute post (the result will be something like {"result":1,"error":"","id":"4da775
我需要一些函数方面的帮助。 我想编写一个插入链表的函数。但不仅仅是中间,如果必须插入前端或末尾,它也必须起作用。 结构: typedef struct ranklist { i
我是一名优秀的程序员,十分优秀!