gpt4 book ai didi

c - 是否可以通过成员地址访问超过结构的大小,并分配足够的空间?

转载 作者:太空狗 更新时间:2023-10-29 16:26:50 27 4
gpt4 key购买 nike

具体来说,下面的代码,标记下面的行,行吗?

struct S{
int a;
};

#include <stdlib.h>

int main(){
struct S *p;
p = malloc(sizeof(struct S) + 1000);
// This line:
*(&(p->a) + 1) = 0;
}

人们争论不休here ,但没有人给出令人信服的解释或引用。

他们的论据略有不同,但本质上是相同的

typedef struct _pack{
int64_t c;
} pack;

int main(){
pack *p;
char str[9] = "aaaaaaaa"; // Input
size_t len = offsetof(pack, c) + (strlen(str) + 1);
p = malloc(len);
// This line, with similar intention:
strcpy((char*)&(p->c), str);
// ^^^^^^^

最佳答案

至少自 1989 年 C 标准化以来,其意图是允许实现检查数组边界以进行数组访问。

成员p->aint 类型的对象。 C11 6.5.6p7说是

7 For the purposes of [additive operators] a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.

因此

&(p->a)

是指向 int 的指针;但它也好像是一个指向长度为 1 的数组的第一个元素的指针,对象类型为 int

现在6.5.6p8允许计算 &(p->a) + 1 这是一个指向刚好超过数组末尾的指针,因此没有未定义的行为。但是,取消引用此类指针是无效的。来自 Appendix J.2在明确说明的地方,在以下情况下行为未定义:

Addition or subtraction of a pointer into, or just beyond, an array object and an integer type produces a result that points just beyond the array object and is used as the operand of a unary * operator that is evaluated (6.5.6).

在上面的表达式中,只有一个数组,一个(好像)只有 1 个元素的数组。如果 &(p->a) + 1 被取消引用,则长度为 1 的数组被越界访问并且 undefined behaviour发生,即

behavior [...], for which [The C11] Standard imposes no requirements

随着note saying that :

Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

最常见的行为是完全忽略这种情况,即表现得好像指针刚刚引用了内存位置,但这并不意味着其他类型的行为是 Not Acceptable 标准的观点——标准允许每一个可以想象和无法想象的结果。


有人说C11的标准文本写得含糊不清,委员会的意图应该是确实允许这样,如果是以前就可以了。这不是真的。阅读委员会对 [缺陷报告 #017,日期为 1992 年 12 月 10 日至 C89] 的回应部分。

Question 16

[...]

Response

For an array of arrays, the permitted pointer arithmetic in subclause 6.3.6, page 47, lines 12-40 is to be understood by interpreting the use of the word object as denoting the specific object determined directly by the pointer's type and value, not other objects related to that one by contiguity. Therefore, if an expression exceeds these permissions, the behavior is undefined. For example, the following code has undefined behavior:

 int a[4][5];

a[1][7] = 0; /* undefined */

Some conforming implementations may choose to diagnose an array bounds violation, while others may choose to interpret such attempted accesses successfully with the obvious extended semantics.

(bolded emphasis mine)

没有理由不将相同的 传递给结构的标量成员,尤其是当 6.5.6p7 规定指向它们的指针应被视为与 行为相同时指向长度为 1 的数组的第一个元素的指针,其元素类型为对象的类型

如果您想寻址连续的struct,您总是可以获取指向第一个成员 的指针并将其转换为指向struct< 的指针 并推进它:

*(int *)((S *)&(p->a) + 1) = 0;

关于c - 是否可以通过成员地址访问超过结构的大小,并分配足够的空间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47224138/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com