UB?在数组启动之前避免“对象” [英] UB? Avoiding ``object'' before array's start

查看:68
本文介绍了UB?在数组启动之前避免“对象”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

自从我在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆