我有一个结构,定义如下:
struct vector
{
(TYPE) *items;
size_t nitems;
};其中类型实际上可以是任何类型,而我有一个类似类型的不可知结构:
struct _vector_generic
{
void *items;
size_t nitems;
};第二种结构用于将第一种任何类型的结构传递给调整大小的函数,例如:
struct vector v;
vector_resize((_vector_generic*)&v, sizeof(*(v->items)), v->nitems + 1);其中,vector_resize试图对向量中给定数量的项进行realloc内存。
int
vector_resize (struct _vector_generic *v, size_t item_size, size_t length)
{
void *new = realloc(v->items, item_size * length);
if (!new)
return -1;
v->items = new;
v->nitems = length;
return 0;
}但是,C标准指出,指向不同类型的指针不需要具有相同的大小。
6.2.5.27:
指向空的指针应具有与指向字符类型的指针相同的表示和对齐要求。39)类似地,指向兼容类型的合格或非限定版本的指针应具有相同的表示和对齐要求。指向结构类型的所有指针应具有相同的表示和对齐要求。指向联合类型的所有指针应具有相同的表示和对齐要求。指向其他类型的指针不需要有相同的表示或对齐要求。
现在我的问题是,我应该担心这段代码可能会在某些体系结构上崩溃吗?
我可以通过重新排序我的结构来修复这个问题,例如,指针类型在末尾?:
struct vector
{
size_t nitems;
(TYPE) *items;
};如果没有,我能做什么?
关于我正在努力实现的目标的参考,见:
https://github.com/andy-graprof/grapes/blob/master/grapes/vector.h
例如,请参见:
https://github.com/andy-graprof/grapes/blob/master/tests/grapes.tests/vector.exp
发布于 2014-11-25 08:07:24
为了便于讨论,让我们忽略C标准正式表示这是未定义的行为。因为未定义的行为仅仅意味着某些事情超出了语言标准的范围:任何事情都可能发生,而C标准没有保证。但是,对于您正在使用的特定系统,可能会有“外部”保证,这是由系统的创建者做出的。
在有硬件的现实世界里,确实有这样的保证。在实践中,只有两件事会出错:
TYPE*具有与void*不同的表示形式或大小。这两种情况似乎都不太可能,可以用静态断言来回避:
static void ct_assert (void) // dummy function never linked or called by anyone
{
struct vector v1;
struct _vector_generic v2;
static_assert(sizeof(v1.items) == sizeof(v2.items),
"Err: unexpected pointer format.");
static_assert(sizeof(v1) == sizeof(v2),
"Err: unexpected padding.");
}现在唯一可能出错的是,如果“指向x的指针”的大小相同,但表示方式与特定系统上的“指向y的指针”不同。我从未听说过现实世界中任何地方都有这样的系统。但当然,没有任何保证:这种晦涩的、非正统的制度可能存在。在这种情况下,这取决于您是否想要支持他们,或者它是否足以使可移植性达到99.99%的所有现有计算机在世界上。
在实践中,系统上唯一有不止一种指针格式的情况是,当您寻址的内存超出了CPU的标准地址宽度时,通常由非标准扩展(如far指针)处理。在所有这些情况下,指针都有不同的大小,您将使用上面的静态断言来检测这些情况。
https://stackoverflow.com/questions/27120486
复制相似问题