Bla*_*iev 7 c pointers c99 ptrdiff-t
C99标准规定:
当减去两个指针时,两个指针都指向同一个数组对象的元素,或者指向数组对象的最后一个元素的元素
请考虑以下代码:
struct test {
int x[5];
char something;
short y[5];
};
...
struct test s = { ... };
char *p = (char *) s.x;
char *q = (char *) s.y;
printf("%td\n", q - p);
Run Code Online (Sandbox Code Playgroud)
这显然打破了上述规则,因为p和q指针指向不同的"数组对象",并且根据规则,q - p差异是未定义的.
但在实践中,为什么这样的事情会导致未定义的行为?毕竟,struct成员按顺序排列(就像数组元素一样),成员之间有任何潜在的填充.确实,填充量会因实现而异,这会影响计算结果,但为什么结果应该是"未定义"?
我的问题是,我们可以假设标准只是对这个问题"无知",还是有充分的理由不扩大这个规则?难道不能将上述规则改为" 两者都应指向同一数组对象的元素或同一结构的成员 "吗?
我唯一怀疑的是分段内存架构,其中成员可能最终分成不同的段.是这样的吗?
我也怀疑这就是为什么GCC定义它自己的原因__builtin_offsetof,以便有一个"符合标准"的offsetof宏定义.
编辑:
正如已经指出的那样,标准不允许对void指针进行算术运算.它是一个GNU扩展,仅在GCC通过时才会触发警告-std=c99 -pedantic.我用void *指针替换char *指针.
char*同一结构的成员地址之间的减法和关系运算符(类型上)定义良好。
任何对象都可以被视为数组unsigned char。
引用N1570 6.2.6.1 第 4 段:
\n\n\n\n\n存储在任何其他对象类型的非位字段对象中的值由n \xc3\x97
\nCHAR_BIT位组成,其中 n 是该类型的对象的大小(以字节为单位)。该值可以被复制到\n n类型的对象中 (例如,通过);得到的字节集被称为值的对象表示。unsigned char []memcpy
...
\n\n\n\n\n我唯一的怀疑是分段内存架构,其中成员可能最终位于不同的段中。是这样吗?
\n
不可以。对于具有分段内存体系结构的系统,通常编译器会施加限制,即每个对象必须适合单个段。或者它可以允许对象占用多个段,但它仍然必须确保指针算术和比较正确工作。
\n| 归档时间: |
|
| 查看次数: |
774 次 |
| 最近记录: |