2D阵列中的指针算术 [英] Pointer arithmetics in 2D arrays

查看:86
本文介绍了2D阵列中的指针算术的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此代码是否合法(根据最严格的可能理解[1]

对标准的解释,无论它是否有效

对已知的所有实现宇宙)?


#include< stdio.h>

void print_square_matrix(int * ptr,int order)

{

int i,j;

for(i = 0; i< order; i ++){

for(j = 0; j < order; j ++)

printf("%3d",* ptr ++);

putchar(''\ n'');

}

}


int main(无效)

{

int matrix [3] [3] = {{157,64,13},

{0,-16,128},

{54,42,-23}}

int * p =& matrix [0] [0]

print_square_matrix(* matrix,3);

返回0;

}


我从不直接溢出数组。在打印出13之后,ptr将点数

指向第一行末尾的元素,这显然是允许的b $ b。那个元素恰好存在并且是矩阵[1] [0]。所以,在换行后,

,printf打印 0然后* ptr是-16。

问题是我错过了什么,或者(p + 3)+ 1没问题和

指向-16,而p +(3 + 1)导致UB?


[1]理智这里的意思是排除那些说int main(无效)

{return 0;符合但不严格符合,因为

状态成功终止的实现定义形式是

返回到主机环境。

解决方案

Army1987说:


此代码是否合法(根据最严格的可能理智[1]

对标准的解释,无论它是否运行

对已知宇宙中的所有实现都有效)?



呃,不。它没有编译。你错过了一个分号。不过,让我们再看看

......


#include< stdio.h>

void print_square_matrix(int * ptr,int order)

{

int i,j;

for(i = 0; i < order; i ++){

for(j = 0; j< order; j ++)

printf("%3d",* ptr ++); < br $> b $ b putchar(''\ n'');

}

}


int main (无效)

{

int matrix [3] [3] = {{157,64,13},

{0, - 16,128},

{54,42,-23}}

int * p =& matrix [0] [0]


这是你错过分号的地方。顺便提一下,什么是p?


print_square_matrix(* matrix,3);



矩阵的类型为int [3] [3],当在

值中使用时衰减为int(*)[3]上下文。所以*矩阵有类型int [3] - 但你也在值

上下文中使用它,所以它变成了int *。传递给

print_square_matrix是合法的,它接受int *。但是在print_square_matrix中,严格来说,你肯定违反了规则。为什么?好吧,你传递一个

指针指向三个整数数组中的第一个元素,但

你在函数中滚动了九个整数。因此,你超越了数组的界限。
。事实上,你完全知道你已经有六个以上的注意事项,那就是

诱惑你做这件事,当然你绝对有可能
/>
侥幸逃脱,但我相信这种行为仍然是,

严格来说,未定义的原因与任何数组绑定的原因相同

违规导致未定义的行为。


< snip>


-

Richard Heathfield

Usenet是一个奇怪的地方 - dmr 29/7/1999
http://www.cpax.org.uk

电子邮件:rjh在上述域名中, - www。




" Richard Heathfield" ; < rj*@see.sig.invalidha scritto nel messaggio

news:3v ************************** **** @ bt.com ...


Army1987说:



[snip]


> int main(void)
{int / matrix [3] [3] = {{ 157,64,13},
{0,-16,128},
{54,42,-23}}
int * p =& matrix [0] [0]



这里是你错过分号的地方。顺便说一句,什么是p?



更糟糕的是我错过了*两个*分号......

(p代表如下。)


假设我有int * p,* q; p =& matrix [0] [0]; q =& matrix [1] [0];

p + = 3;

现在p和q相等。证明:p + 3等于(int *)((unsigned char *)p + 3 *

sizeof * p);

q等于& *(矩阵[1] + 0)= matrix [1] = *(矩阵+ 1)=(int *)((无符号

char *)矩阵+ sizeof *矩阵)

=( int *)((unsigned char *)matrix + sizeof(int [3]))=(int *)((unsiged

char *)matrix + 3 * sizeof(int))

但是,IIUC,q ++现在是合法的,p ++不是。

对吗?


Army1987说:


>

" Richard Heathfield" < rj*@see.sig.invalidha scritto nel messaggio

news:3v ************************** **** @ bt.com ...


> Army1987说:



[snip] ]


>> int main(void)
{int / matrix [3] [3 ] = {{157,64,13},
{0,-16,128},
{54,42,-23}}
int * p =& matrix [0 ] [0]


这里是你错过分号的地方。顺便说一句,什么是p?



更糟糕的是我错过了*两个*分号...



所以你确实。


(p代表如下。)


假设我有int * p,* q; p =& matrix [0] [0]; q =& matrix [1] [0];

p + = 3;



嗯,是的,你可以做到这一点,你现在指出一个超出

矩阵[0]的结尾,只要你没有取消引用,这是合法的。


现在p和q是相等的。



我不认为你可以比较它们,是吗?毕竟,

中的一个是指向矩阵[0]的一端或一端,而

的另一个指向 - 或者 - 矩阵的结束[1],这些是不同的对象。 (我必须说我觉得标准在这个

点很傻,因为阵列保证是连续的。)


-

Richard Heathfield

Usenet是一个奇怪的地方 - dmr 29/7/1999
http://www.cpax.org.uk

电子邮件:rjh在上述域名中, - www。


Is this code legal (according to the strictest possible sane[1]
interpretation of the standard, regardless of wheter it does work
on all implementations in the known universe)?

#include <stdio.h>
void print_square_matrix(int *ptr, int order)
{
int i, j;
for (i = 0; i < order; i++) {
for (j = 0; j < order; j++)
printf("%3d ", *ptr++);
putchar(''\n'');
}
}

int main(void)
{
int matrix[3][3] = { {157, 64, 13},
{ 0, -16, 128},
{ 54, 42, -23} }
int *p = &matrix[0][0]
print_square_matrix(*matrix, 3);
return 0;
}

I never directly overflow an array. After 13 is printed, ptr points
to an element past the end of the first row, which is explicitly
allowed. That element happens to exist and is matrix[1][0]. So,
after the newline, the printf prints " 0 " and then *ptr is -16.
The question is "Am I missing something, or (p + 3) + 1 is ok and
points to -16, while p + (3 + 1) causes UB?"

[1] "sane" here means "excluding those who say int main(void)
{ return 0; } is conforming but not strictly conforming because an
implementation-defined form of the status successful termination is
returned to the host environment".

解决方案

Army1987 said:

Is this code legal (according to the strictest possible sane[1]
interpretation of the standard, regardless of wheter it does work
on all implementations in the known universe)?

Er, no. It doesn''t compile. You missed a semicolon. But let''s take a
closer look anyway...

#include <stdio.h>
void print_square_matrix(int *ptr, int order)
{
int i, j;
for (i = 0; i < order; i++) {
for (j = 0; j < order; j++)
printf("%3d ", *ptr++);
putchar(''\n'');
}
}

int main(void)
{
int matrix[3][3] = { {157, 64, 13},
{ 0, -16, 128},
{ 54, 42, -23} }
int *p = &matrix[0][0]

Here''s where you missed your semicolon. Incidentally, what is p for?

print_square_matrix(*matrix, 3);

matrix has type int[3][3], which decays to int(*)[3] when used in a
value context. So *matrix has type int[3] - but you use this in a value
context too, so it becomes int *. That''s legal to pass to
print_square_matrix, which takes int *. But in print_square_matrix, you
are, strictly speaking, breaking the rules. Why? Well, you pass a
pointer that points to the first element in an array of three ints, but
you roll through nine ints in your function. Therefore, you''re
overstepping the bounds of an array. The fact that you know perfectly
well that you have six more ints immediately following is what has
tempted you to do this, and of course you are overwhelmingly likely to
get away with it, but I believe that the behaviour is nevertheless,
strictly speaking, undefined for the same reason that any array bounds
violation leads to undefined behaviour.

<snip>

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.



"Richard Heathfield" <rj*@see.sig.invalidha scritto nel messaggio
news:3v******************************@bt.com...

Army1987 said:

[snip]

>int main(void)
{
int matrix[3][3] = { {157, 64, 13},
{ 0, -16, 128},
{ 54, 42, -23} }
int *p = &matrix[0][0]


Here''s where you missed your semicolon. Incidentally, what is p for?

What''s worse is that I missed *two* semicolons...
(p is for the example below.)

Suppose I have int *p, *q; p = &matrix[0][0]; q = &matrix[1][0];
p += 3;
Now p and q are equal. PROOF: p + 3 equals (int *)((unsigned char *)p + 3 *
sizeof *p);
q equals &*(matrix[1] + 0) = matrix[1] = *(matrix + 1) = (int *)((unsigned
char *)matrix + sizeof *matrix)
= (int *)((unsigned char *)matrix + sizeof (int [3])) = (int *)((unsiged
char *)matrix + 3 * sizeof(int))
But, IIUC, q++ now is legal and p++ isn''t.
Right?


Army1987 said:

>
"Richard Heathfield" <rj*@see.sig.invalidha scritto nel messaggio
news:3v******************************@bt.com...

>Army1987 said:

[snip]

>>int main(void)
{
int matrix[3][3] = { {157, 64, 13},
{ 0, -16, 128},
{ 54, 42, -23} }
int *p = &matrix[0][0]


Here''s where you missed your semicolon. Incidentally, what is p for?


What''s worse is that I missed *two* semicolons...

So you did.

(p is for the example below.)

Suppose I have int *p, *q; p = &matrix[0][0]; q = &matrix[1][0];
p += 3;

Um, yeah, you can do that, and you''re now pointing one beyond the end of
matrix[0], which is legal as long as you don''t dereference.

Now p and q are equal.

I don''t think you''re allowed to compare them, are you? After all, one of
them is pointing into-or-one-past-the-end-of matrix[0], whereas the
other is pointing into-or-one-past-the-end-of matrix[1], and these are
different objects. (I must say I find the Standard rather silly at this
point, given that arrays are guaranteed to be contiguous.)

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.


这篇关于2D阵列中的指针算术的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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