Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
指针减法在C中什么时候没有定义? char*buf=malloc(bufsize) char*ptr=buf; … while(条件){ ptrdiff\u t offset=ptr-buf;//bufsize){ //我们需要更多的空间 bufsize+=128; buf=realloc(buf,bufsize); ptr=buf+offset;//buf可能位于一个全新的位置 } *ptr++=…//写入此字节 }_C_Arrays_Pointers_Undefined Behavior_Pointer Arithmetic_C11 - Fatal编程技术网

指针减法在C中什么时候没有定义? char*buf=malloc(bufsize) char*ptr=buf; … while(条件){ ptrdiff\u t offset=ptr-buf;//bufsize){ //我们需要更多的空间 bufsize+=128; buf=realloc(buf,bufsize); ptr=buf+offset;//buf可能位于一个全新的位置 } *ptr++=…//写入此字节 }

指针减法在C中什么时候没有定义? char*buf=malloc(bufsize) char*ptr=buf; … while(条件){ ptrdiff\u t offset=ptr-buf;//bufsize){ //我们需要更多的空间 bufsize+=128; buf=realloc(buf,bufsize); ptr=buf+offset;//buf可能位于一个全新的位置 } *ptr++=…//写入此字节 },c,arrays,pointers,undefined-behavior,pointer-arithmetic,c11,C,Arrays,Pointers,Undefined Behavior,Pointer Arithmetic,C11,这是有效的还是未定义的 我本以为它是有效的,但我读到一些关于它未定义的东西,所以我用谷歌搜索了一下。这些链接似乎不可避免地声称它是未定义的: 但是,在这些问题中没有提及: 这些都是关于不是两个指针在同一个“数组”中。这是否意味着堆栈上有一个普通的旧C数组 如果它未定义,对我来说似乎很奇怪……当我可以访问一个常量指针和一个移动指针时,为什么要强迫我携带一个计数器变量?指针指向由malloc返回的内存块,并将其计数为同一数组: 7.22.3内存管理功能 1-该 如果分配成功,[从

这是有效的还是未定义的

我本以为它是有效的,但我读到一些关于它未定义的东西,所以我用谷歌搜索了一下。这些链接似乎不可避免地声称它是未定义的:

但是,在这些问题中没有提及:

这些都是关于不是两个指针在同一个“数组”中。这是否意味着堆栈上有一个普通的旧C数组


如果它未定义,对我来说似乎很奇怪……当我可以访问一个常量指针和一个移动指针时,为什么要强迫我携带一个计数器变量?

指针指向由
malloc返回的内存块,并将其计数为同一数组:

7.22.3内存管理功能 1-该 如果分配成功,[从
malloc
]返回的指针[…]可以分配给 指向任何类型对象[…]的指针,然后使用 访问所分配空间中的此类对象或此类对象数组(直到 显式解除分配)


ptrdiff\u t offset=ptr-buf;// 这是一种定义的行为,只要不超过数组末尾的一个元素。C99§6.5.6/8说明了添加指针和整数:

[…]如果指针和 操作数和结果指向同一数组对象的元素,或超过最后一个的元素 阵列对象的元素,评估不应产生过流;否则 行为是不确定的。[……]

以及关于减法的第9段:

9) 减去两个指针时,两个指针都应指向同一数组对象的元素, 或超过数组对象最后一个元素一次;[……]

以及§7.20.3/1:

如果分配失败,指针将返回 SUCCESS适当对齐,以便可以将其指定给指向任何类型对象的指针 然后用于访问分配空间中的此类对象或此类对象的数组 (直到空间被明确释放)

因此,一旦将
ptr
移动到最后一个数组元素之后的元素之外,执行指针减法就是未定义的行为


我确实相信有一些系统会因为这段代码而表现不好,尽管我不能说出任何系统的名字。理论上,
malloc()
可以返回指向可寻址内存结尾之前的指针,例如,如果请求255个字节,则在32位系统上可能返回0xFFFF00,因此在结尾之外创建指针将导致溢出。指针表示上的整数溢出也可能触发某种陷阱(例如,如果指针存储在特殊寄存器中)。虽然我不知道有任何系统具有这些属性,但C标准肯定允许它们的存在。

谢谢。我不确定这是否只是使用了不同的术语,或者我只是缺少了一些东西。标准的某些部分会建议这样做,比如
struct foo char arr[5][5];}*p=malloc(25)
,左值
p->arr[x][y]x
的值是多少,都不会为范围0..4之外的
y
的任何值定义code>,即使索引项位于相同的分配区域内。现在还不清楚如何才能
p->arr[y]
得到一个可以索引到该区域内所有地址的指针。是的,但是“…同一数组对象的元素…”让我感到困惑。malloc’d内存块是“数组对象”吗?ecatmur在回答中引用了标准的相关段落。作为旁注,甚至定义为:
inta=0;int*p=&a;int*q=&a+1;ptrdiff_t d=p-q
因此,一旦将ptr移动到最后一个数组元素之后的元素之外,执行指针减法就是未定义的行为。除非
ptr
超过最后一个数组元素。理论上,malloc可以返回指向可寻址内存末尾之前的指针,例如,如果您请求256字节,它可以在32位系统上返回0xFFFF00,实际上它不能返回,因为超过最后一个数组元素规则。C标准在一个非规范性脚注中说:以这种方式来看,一个实现只需在对象结束后提供一个额外字节(可能与程序中的另一个对象重叠),以满足“超过最后一个元素一个”的要求。对不起,我错过了一次只增加一个字节的部分,请参阅更新。一次执行一个字节是可以的,但是如果您要以更大的增量跳转,并且超过一个字节,则这是未定义的行为。
char *buf = malloc(bufsize)
char *ptr = buf;
…
while(condition) {
    ptrdiff_t offset = ptr - buf;    // <========== THIS LINE

    // offset will never be negative because we only ever *increase* ptr
    if ((size_t)offset > bufsize) {
        // we need more room
        bufsize += 128;
        buf = realloc(buf, bufsize);
        ptr = buf + offset;  // buf might be in a completely new location
    }
    *ptr++ = …  // write this byte
}
ptrdiff_t offset = ptr - buf;    // <========== THIS LINE