UB?在数组启动之前避免“对象” [英] UB? Avoiding ``object'' before array's start
问题描述
自从我在c.l.c上提出查询以来已经很长时间了。我的工作
环境演变为主要是C ++和Perl,只有很少的C,所以随着时间的推移我已经忘了很多了。
这将重新讨论在数组开始之前减少指向
不存在位置的指针的讨论主题。我一直在重读
K.N. King''C编程:现代方法'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''我认为大部分
常客都可以访问这本书或代码(它在网上)。
如下,替代方法(是的,我知道还有其他方法)
正确地向后通过数组进行交互而不会在a开始之前嗅探
不存在的元素'''?
#include< stdio.h>
int main(无效)
{
int * p,a [] = {1,2,3};
size_t n = sizeof a / sizeof * a;
for(p = a + n - 1; p + 1> = a + 1; --p)
printf("%i \ n",* p) ;
返回0;
}
Bob Nelson说:
< snip>
>
以下是替代方法(是的,我知道还有其他方法)
在a'''开头之前没有嗅探
不存在的元素,这是正确的向后整理数组吗?
#include< ; stdio.h>
int main(无效)
{
int * p,a [] = {1, 2,3};
size_t n = sizeof a / sizeof * a;
for(p = a + n - 1; p + 1> = a + 1; --p)
a + n给出了一个仅仅是合法的但是合法的参考
非存在元素a [n]。 a + n - 1因此很好。 p + 1,在第一个
迭代中,指向同一个只是合法的不存在的元素。并且p $ / $
永远不会减少到低于a。是的,没关系。
-
Richard Heathfield
Usenet是一个奇怪的地方 - dmr 29/7/1999
http://www.cpax.org.uk
电子邮件:rjh在上面的域名(但显然放弃了www)
Richard Heathfield写道:
< blockquote class =post_quotes>
Bob Nelson说:
< snip>
以下是替代方法(是的,我知道还有其他方法)
正确通过数组没有在'a''''开始之前嗅探
不存在的元素?
#include< stdio.h>
int main(无效)
{
int * p,a [] = {1,2,3};
size_t n = sizeof a / sizeof * a;
for(p = a + n - 1; p + 1> = a + 1; - -p)
a + n给出了一个仅仅是合法的但仍然合法的参考
不存在的元素a [n] 。 a + n - 1因此很好。 p + 1,在第一个
迭代中,指向同一个只是合法的不存在的元素。并且p $ / $
永远不会减少到低于a。所以,是的,没关系。
p永远不会减少到? p + 1> = a + 1(p> = a)怎么会是
假,那么?
Richard Heathfield在07/25/06 15:19写道:
Bob Nelson说:
< snip>
>>以下是替代方法(是的,我知道还有其他方法)
纠正在数组中向后进行交互,而不是在a的开始之前嗅探
不存在的元素吗?
#include< stdio.h>
int main(void)
{*> int * p,a [] = {1,2,3};
size_t n = sizeof a / sizeof * a;
for(p = a + n - 1; p + 1> = a + 1; --p)
a + n给出了一个仅仅是合法的但仍然合法的参考
不存在的元素a [n]。 a + n - 1因此很好。 p + 1,在第一个
迭代中,指向同一个只是合法的不存在的元素。并且p $ / $
永远不会减少到低于a。所以,是的,没关系。
让我们玩电脑吧!
初始值:p = a + 3-1 == p = a + 2(* p == 3)
测试:p + 1> = a + 1 == a + 3> = a + 1 == true
身体执行
步骤:p =(a + 2)-1 == p = a + 1(* p == 2)
测试:p + 1> = a + 1 == a + 2> = a + 1 == true
正文执行
步骤:p =(a + 1)-1 == p = a + 0(* p == 1)
测试:p + 1> = a + 1 == a + 1> = a + 1 == true >
身体执行
步骤:p =(a + 0)-1 ==未完成行为
测试:p + 1> = a + 1 = =未定义的行为
一对加号在测试中似乎没有
任何有用的效果。只要它们有效(也就是说,只要
p指向a的实际元素),它们就可以从双方减去
,所以测试与`p相同
意义上的> = a''产生相同的结果或两者都无效。
装饰品不会扩展有效范围。
要在数组中向后运行指针,我建议用这样的方式写入循环:
for(p = a + n; pa;){
--p;
/ *循环体* /
}
风险略高的形式是
for(p = a + n; p--a;){
/ * loop body * / < br $>
}
....通过尝试计算无效指针而产生的罪行
值a-1,但避免复合进一步犯了这个无效价值的
算术。
(我不知道King的书推荐的是什么表格。)
-
Er ********* @ sun.com
It''s been a long time since I''ve posed a query here on c.l.c. My work
environment evolved to primarily C++ and Perl with very little C, so I''ve
forgotten quite a lot over time.
This revisits the much-discussed topic of decrementing a pointer to the
non-existent location before the start of an array. I''ve been re-reading
K.N. King''s ``C Programming: A Modern Approach'''' and came across
``reverse2.c'''' on page 228, which raised a red flag. I presume most of the
regulars have access to the book or to the code (it''s on the web).
Is the following, alternate approach (yes, I know there are other ways)
correct to interate backwards through the array without sniffing at the
non-existent element before the start of ``a''''?
#include <stdio.h>
int main(void)
{
int *p, a[] = { 1, 2, 3 };
size_t n = sizeof a / sizeof *a;
for (p = a + n - 1; p + 1 >= a + 1; --p)
printf ("%i\n", *p);
return 0;
}
Bob Nelson said:
<snip>>
Is the following, alternate approach (yes, I know there are other ways)
correct to interate backwards through the array without sniffing at the
non-existent element before the start of ``a''''?
#include <stdio.h>
int main(void)
{
int *p, a[] = { 1, 2, 3 };
size_t n = sizeof a / sizeof *a;
for (p = a + n - 1; p + 1 >= a + 1; --p)a + n gives an only-just-legal but nevertheless legal reference to the
non-existent element a[n]. a + n - 1 is therefore fine. p + 1, on the first
iteration, points to that same only-just-legal non-existent element. And p
is never decremented below a. So yes, it''s fine.
--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Richard Heathfield wrote:Bob Nelson said:
<snip>
Is the following, alternate approach (yes, I know there are other ways)
correct to interate backwards through the array without sniffing at the
non-existent element before the start of ``a''''?
#include <stdio.h>
int main(void)
{
int *p, a[] = { 1, 2, 3 };
size_t n = sizeof a / sizeof *a;
for (p = a + n - 1; p + 1 >= a + 1; --p)
a + n gives an only-just-legal but nevertheless legal reference to the
non-existent element a[n]. a + n - 1 is therefore fine. p + 1, on the first
iteration, points to that same only-just-legal non-existent element. And p
is never decremented below a. So yes, it''s fine.p is never decremented below a? How can p + 1 >= a + 1 (p >= a) ever be
false, then?
Richard Heathfield wrote On 07/25/06 15:19,:Bob Nelson said:
<snip>
>>Is the following, alternate approach (yes, I know there are other ways)
correct to interate backwards through the array without sniffing at the
non-existent element before the start of ``a''''?
#include <stdio.h>
int main(void)
{
int *p, a[] = { 1, 2, 3 };
size_t n = sizeof a / sizeof *a;
for (p = a + n - 1; p + 1 >= a + 1; --p)
a + n gives an only-just-legal but nevertheless legal reference to the
non-existent element a[n]. a + n - 1 is therefore fine. p + 1, on the first
iteration, points to that same only-just-legal non-existent element. And p
is never decremented below a. So yes, it''s fine."Let''s play computer!"
Init: p = a+3-1 == p = a+2 (*p == 3)
Test: p+1 >= a+1 == a+3 >= a+1 == true
Body executes
Step: p = (a+2)-1 == p = a+1 (*p == 2)
Test: p+1 >= a+1 == a+2 >= a+1 == true
Body executes
Step: p = (a+1)-1 == p = a+0 (*p == 1)
Test: p+1 >= a+1 == a+1 >= a+1 == true
Body executes
Step: p = (a+0)-1 == UNDEFINED BEHAVIOR
Test: p+1 >= a+1 == UNDEFINED BEHAVIOR
The pair of "plus ones" in the test don''t seem to have
any useful effect. Whenever they are valid (that is, whenever
p points to an actual element of a) they can be subtracted
from both sides, so the test is the same as `p >= a'' in the
sense that both produce the same result or both are invalid.
The decorations do not expand the valid range.
To run a pointer backwards through an array, I suggest
writing the loop this way:
for (p = a + n; p a; ) {
--p;
/* loop body */
}
A slightly riskier form is
for (p = a + n; p-- a; ) {
/* loop body */
}
.... which sins by trying to compute the invalid pointer
value a-1, but avoids compounding the sin by doing further
arithmetic with that invalid value.
(I don''t know what formulation King''s book recommends.)
--
Er*********@sun.com
这篇关于UB?在数组启动之前避免“对象”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!