- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
在对通用 vector 进行一些研究后,我在 this question 上询问了相关问题,我想知道是否有任何方法可以检查库的每个实例是否只针对每种类型执行一次。
这是当前头文件的样子:
#ifndef VECTOR_GENERIC_MACROS
#define VECTOR_GENERIC_MACROS
#ifndef TOKENPASTE
#define TOKENPASTE(a, b) a ## b
#endif
#define vector_t(T) TOKENPASTE(vector_t_, T)
#define vector_at(T) TOKENPASTE(*vector_at_, T)
#define vector_init(T) TOKENPASTE(vector_init_, T)
#define vector_destroy(T) TOKENPASTE(vector_destroy_, T)
#define vector_new(T) TOKENPASTE(vector_new_, T)
#define vector_delete(T) TOKENPASTE(vector_delete_, T)
#define vector_push_back(T) TOKENPASTE(vector_push_back_, T)
#define vector_pop_back(T) TOKENPASTE(vector_pop_back_, T)
#define vector_resize(T) TOKENPASTE(vector_resize_, T)
#define vector_reserve(T) TOKENPASTE(vector_reserve_, T)
#endif
typedef struct {
size_t size;
size_t capacity;
TYPE *data;
} vector_t(TYPE);
inline TYPE vector_at(TYPE)(vector_t(TYPE) *vector, size_t pos);
void vector_init(TYPE)(vector_t(TYPE) *vector, size_t size);
void vector_destroy(TYPE)(vector_t(TYPE) *vector);
inline TYPE *vector_new(TYPE)(size_t size);
inline void vector_delete(TYPE)(vector_t(TYPE) *vector);
void vector_push_back(TYPE)(vector_t(TYPE) *vector, TYPE value);
inline TYPE vector_pop_back(TYPE)(vector_t(TYPE) *vector);
inline void vector_resize(TYPE)(vector_t(TYPE) *vector, size_t size);
void vector_reserve(TYPE)(vector_t(TYPE) *vector, size_t size);
然后可以将 header 与源定义一起包含在内:
#include <stdio.h>
#define TYPE int
#include "vector.h"
#include "vector.def"
#undef TYPE
int main()
{
vector_t(int) myVectorInt;
vector_init(int)(&myVectorInt, 0);
for (int i = 0; i < 10; ++i)
vector_push_back(int)(&myVectorInt, i);
for (int i = 0; i < myVectorInt.size; ++i)
printf("%d ", ++vector_at(int)(&myVectorInt, i));
vector_destroy(int)(&myVectorInt);
return 0;
}
我想确保每个 TYPE 只包含最后一个 endif 下面的内容。
显然,#ifdef VECTOR_INSTANCE(TYPE) 不起作用,所以我真的没有想法......
最佳答案
这是一个虽然问题,但是,当我问 similar question 时,我也对此事感兴趣前一段时间给你的。
我的结论是,如果您打算使用许多不同类型的 vector (或者,使用更准确的命名,动态数组),那么拥有所有这些函数是一种浪费 vector_##TYPE##_reserve()
、vector_##type##_resize()
等...多次。
相反,将这些函数在单独的 .c
文件中只定义一次,使用您的类型的大小作为额外参数,会更高效、更简洁。这些函数的原型(prototype)在单独的 .h
文件中。然后,相同的 .h
文件将提供为您自己的类型生成函数包装器的宏,这样您就不会看到它使用大小作为额外参数。
例如,您的 vector.h
header 将包含以下内容:
/* Declare functions operating on a generic vector type */
void vector_generic_resize(void *vector, size_t size, size_t data_size);
void vector_generic_push_back(void *vector, void *value, size_t data_size);
void *vector_generic_pop_back(void *vector, size_t data_size);
void vector_generic_init(void *vector, size_t size, size_t data_size);
void vector_generic_destroy(void *vector) ; // I don't think data_size is needed here
/* Taken from the example in the question */
#define VECTOR_DEFINITION(type)\
typedef struct {\
size_t size;\
size_t capacity;\
type *data;\
} vector_ ## type ## _t;\
/* Declare wrapper macros to make the above functions usable */
/* First the easy ones */
#define vector_resize(vector, size) vector_generic_resize(vector, size, sizeof(vector.data[0]))
#define vector_init(vector, size) vector_generic_init(vector, size, sizeof(vector.data[0]))
/* Type has to be given as an argument for the cast operator */
#define vector_pop_back(vector, type) (*(type*)(vector_generic_pop_back(vector, sizeof(vector.data[0]))))
/* This one is tricky, if 'value' is a constant, it's address cannot be taken.
I don't know if any better workarround is possible. */
#define vector_push_const(vector, type, value) \
{ \
type temp = value; \
vector_generic_push_back(vector, &temp, sizeof(vector.data[0]));\
}
/* Equivalent macro, but for pushing variables instead of constants */
#define vector_push_var(vector, value) vector_generic_push_back(vector, &value, sizeof(vector.data[0]))
/* Super-macro rediriging to constant or variable version of push_back depending on the context */
#define GET_MACRO(_1,_2,_3,NAME,...) NAME
#define vector_push_back(...) GET_MACRO(__VA_ARGS__, vector_push_const, vector_push_var)(__VA_ARGS__)
/* This macro isn't really needed, but just for homogenity */
#define vector_descroy(vector) vector_generic_destroy(vector)
然后可以按照您在链接的示例中所说的那样使用函数,但 vector_generic_push_back 是一个重要的异常(exception),不幸的是,每次都必须将类型指定为额外的宏参数。
所以有了这个解决方案
.c
文件中执行 VECTOR_DEFINITION()
,避免使用相同类型声明它两次的风险vector_generic_pop_back()
函数不返回任何内容,就像它们在 C++ 语言中所做的那样,这样如果您同时执行这两个技巧,就永远不需要使用宏中明确的类型名称。作为引用,您在问题中链接的示例中发布的主要功能必须像这样进行调整:
#include <stdio.h>
#include <stdlib.h>
#include "vector.h"
typedef unsigned int uint;
typedef char* str;
VECTOR_DEFINITION(uint)
VECTOR_DEFINITION(str)
int main()
{
vector_uint_t vector;
vector_init(&vector, 10);
for (unsigned int i = 0; i < vector.size; ++i)
vector.data[i] = i;
for (unsigned int i = 0; i < 10; ++i)
vector_push_back(&vector, i);
/* When pushing back a constant, we *have* to specity the type */
/* It is OK to use C keywords as they are supressed by the preprocessor */
vector_push_back(&vector, unsigned int, 12);
for (unsigned int i = 0; i < vector.size; ++i)
printf("%d ", vector.data[i]);
printf("\n");
vector_destroy(&vector);
vector_str_t sentence;
vector_init(&sentence, 0);
vector_push_back(&sentence, "Hello");
vector_push_back(&sentence, str, "World!"); /* Also possible, less efficient */
vector_push_back(&sentence, "How");
vector_push_back(&sentence, "are");
vector_push_back(&sentence, "you?");
for (unsigned int i = 0; i < sentence.size; ++i)
printf("%s ", sentence.data[i]);
printf("\n");
vector_destroy(&sentence);
return 0;
}
关于c - C 中的一次性伪通用 header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29052877/
我在让“@header”或任何其他@规则在ANTLR中工作时遇到麻烦。具有非常基本的语法,如下所示: grammar test; options { language = CSharp2;
我对来源和寄宿有疑问 我有一个ajax页面“Page A”,它将称为ajax提要“Page B” 我看到来自ajax调用的“页面B”的请求 header 具有源“http://mydomain.com
我在 pandas 中使用了数据透视表并获得了所需的数据框格式,但现在我有两行标题。数据透视表后的结果数据框如下: scenario Actual Plan
我在 pandas 中使用了数据透视表并获得了所需的数据框格式,但现在我有两行标题。数据透视表后的结果数据框如下: scenario Actual Plan
我想在主机将它们发送到网络之前修改数据包头(IP 头、TCP 头)。 例如,如果我使用 firefox 进行浏览,那么我想拦截所有来自 firefox 的数据包并修改 IP/TCP header ,然
我的 header 内容被包装到#header 中,但是当我设置边框显示结构时,它显示我的#header 的内容出现在#header 本身之后。可能是什么问题?这是我的代码: #header { bo
我是一名 Web 开发人员,使用过 PHP 和 .NET。有一年多的 Web 工作经验,我一直无法彻底了解浏览器缓存功能,希望这里的 Web Gurus 可以帮助我。我心中的问题是: 浏览器实际上是如
伙计们,我有一个问题,我不知道如何在一个 header 中连接多个 header ,我们称它为“主 header ”并使用该 header 中的函数,例如 // A.h #include class
我有一个包含 SOAP 消息的 XMLHTTPRequest。 我想添加用于标识消息并将由 C# Web 服务使用的 guid。 GUID 的目标是识别特定用户,并应护送所有用户请求以在服务器上进行身
我一直在阅读粘性标题,这是我目前所发现的。第一个粘性 header 效果很好,但是当它遇到第一个 header 时,我如何向上滚动第一个 header 并使第二个 header 卡住? http://
我想将当前基于 TableView 的数据网格转换为新的 UICollectionView 类。 这就是我当前的网格的样子: 我的网格有两个标题: 年份(2006a、2007a 等)和 类型(“收入”
我目前正在使用 Apollo 服务器。我正在尝试在响应 header 中设置一个属性。并且此属性是从客户端 graphQL 请求 header 中检索的。 我在网上查了一下。并看到了诸如使用插件或扩展
我的 Controller 的方法需要设置一个标题,例如X-Authorization .创建新对象( store Action )后,我执行转发以显示新创建的对象( show Action ): $
我正在研究一些关于 VLAN 的事情,发现了 VLAN 标签 和 header 。 如果我们有标准 802.3 以太网帧 的 MTU(1518 字节), header 802.3 中包含什么? 另外,
我是放心和 Java 的新手,我正在尝试做一个非常基本的测试来检查 API 的响应是否为 200 ok。 谁能告诉我我需要在下面的脚本中更改什么才能传递多个 header Id、Key 和 ConId
在我的项目中,我需要知道 zlib header 是什么样的。我听说它相当简单,但我找不到 zlib header 的任何描述。 例如,它是否包含魔数(Magic Number)? 最佳答案 zlib
我正在使用 JMeter 测试 HTTP 服务器,该服务器接受并验证 APIKey 并在成功时返回一个有时限的 token 。如果我有 token ,我想发送一个 token ;如果没有,我想发送一个
以太网 header 是什么样的? 是吗: 1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|
我们的应用程序支持 CORS 配置 header 。我在两个不同的主机上分别配置了 testApp。两种设置都相互独立工作。host1 上的应用程序配置有 CORS header Access-Con
tlhelp32.h 不包含 windows.h 本身是有原因的吗?我一直在与大量的编译器错误作斗争,因为我在包含 tlhelp32.h 之后包含了 windows.h。这是设计决定还是出于什么原因?
我是一名优秀的程序员,十分优秀!