为什么这个演员是必要的 [英] Why is this cast nessasary

查看:70
本文介绍了为什么这个演员是必要的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



问题


是否需要这个演员?

编译器是8位,整数是16位。

代码用于环形缓冲区


如果没有此编译器中的强制转换,它就无法工作。

我看到它有效没有它的地方。

哪种方式是正确的(或者它应该重要吗?)


谢谢Neil




unsigned char t_in;

unsigned char t_out;


/ * ---------- -------------------------------------------------- ---- * /

位com_putchar(unsigned char c)

{


/ *如果缓冲区已满,返回错误值。* /

if((TBUF_SIZE - (unsigned char)(t_in - t_out))< = 2)

return(1);


/ *更多代码* /

/ *更多代码* /

/ *更多代码* /

/ *更多代码* /


返回(0);

}

解决方案

Ne il< Ne ******* @ worldnet.att.netwrites:


问题


应该这个演员表是必要的吗?

编译器是8位,整数是16位。



我不知道你的意思是编译器是8位。我会假设

char是8位(CHAR_BIT == 8)和sizeof(int)== 2.


代码用于环形缓冲区


如果没有此编译器中的强制转换,它将无法工作。



无法说出你的意思不起作用。它是否b / b
无法编译?它会给你不同于预期的结果吗?你有什么期望,你得到了什么?


我看到它在没有它的地方工作了。

哪种方式是对的(或者它应该重要吗?)



[...]

..


unsigned char t_in;

unsigned char t_out;


/ * --------------- ------------------------------------------------- * /

位com_putchar(unsigned char c)



大概是位声明在某处。


{


/ *如果缓冲区已满,则返回错误值。* /

if((TBUF_SIZE - (unsigned char)(t_in - t_out))< = 2)



同样TBUF_SIZE。


在表达式中,任何unsigned char类型的子表达式都将被提升为int或unsigned int。如果int可以保存unsigned char类型的所有可能值,那么它将被提升为int



几乎总是如此)。


所以t_in - t_out的类型是int,它可以是正数,
负数或零。转换为unsigned char会产生正的
或零结果。例如,如果t_in - t_out为-1,则转换

可能会产生255.


然后从TBUF_SIZE中减去该结果,但我们不知道

TBUF_SIZE的值,甚至类型。


这就是我可以告诉你的全部内容。


返回(1);


/ *更多代码* /



[。 ..]


>

return(0);

}


一个次要的样式点:返回陈述中的括号不是必需的
。他们是无害的,但我(而且,我认为,大多数是程序员)

更喜欢:

返回1;

...

返回0;


-

Keith Thompson(The_Other_Keith) ks *** @ mib.org < http://www.ghoti.net/~kst>

圣地亚哥超级计算机中心< *< http ://users.sdsc.edu/~kst>

我们必须做点什么。这是事情。因此,我们必须这样做。


Keith Thompson写道:


Neil< Ne **** ***@worldnet.att.netwrites:


>问题

是否需要这个演员?
编译器是8位整数是16位。



我不知道你的意思是编译器是8位。我会假设

char是8位(CHAR_BIT == 8)和sizeof(int)== 2.


>该代码用于环形缓冲区

如果没有此编译器中的强制转换,它将无法工作。



无法说出你的意思不起作用。它是否b / b
无法编译?它会给你不同于预期的结果吗?你有什么期望,你得到了什么?


>我看到它在没有它的地方工作。
哪种方式是正确的(或应该这有关系吗?)



[...]



> unsigned char t_in;
unsigned char t_out;

/ * ---------- -------------------------------------------------- ---- * /
位com_putchar(unsigned char c)



大概是位声明在某处。


> {

/ *如果缓冲区已满,则返回错误值。* /
if((TBUF_SIZE - (unsigned char)(t_in - t_out))< = 2)



同样TBUF_SIZE。


在表达式中,任何unsigned char类型的子表达式都将被提升为int或unsigned int。如果int可以保存unsigned char类型的所有可能值,那么它将被提升为int



几乎总是如此)。


所以t_in - t_out的类型是int,它可以是正数,
负数或零。转换为unsigned char会产生正的
或零结果。例如,如果t_in - t_out为-1,则转换

可能会产生255.


然后从TBUF_SIZE中减去该结果,但我们不知道

TBUF_SIZE的值,甚至类型。


这就是我可以告诉你的全部内容。


>返回(1);

/ *更多代码* /



[...]


>返回(0);
}



小样式点:返回语句中的括号不是必需的
。他们是无害的,但我(而且,我认为,大多数是程序员)

更喜欢:

返回1;

...

返回0;



对不起我不完整:

8位,如PIC16 CPU而非PC 。 8位字符和16位整数

位实际上有点,但我认为没关系。


TBUF_SIZE为此目的假设为32。 />

括号我试图使代码保持一致。原来必须有

有它们。


不起作用意味着编译,但不能按预期工作。数学

不起作为环形缓冲区包装。没有检测到完整的缓冲区

并且数据被覆盖了。


所以它可能是一个整数提升问题(在这个问题上有意义) />
case)。另一个编译器有一个非标准的无促销选项。

第二个用于使用无符号长整数的32位编译器


我讨厌修复一些东西而不理解修复,或抱怨编译器在做正确的事情时的b
。我可以再看一遍

并查看编译器是否匹配数学如果它全部被提升。


Neil写道:


...


>> / *如果缓冲区已满,则返回错误值。* /
if((TBUF_SIZE - (unsigned char)(t_in - t_out))< = 2)


...



您仍然忘记提及一个重要细节:'TBUF_SIZE'的_type_是什么?


假设''TBUF_SIZE''具有相对大的值。无符号类型。对于

示例,让我们假设''TBUF_SIZE''的类型为''size_t''。我们也假设

''TBUF_SIZE'的值等于256.


现在,考虑如果我们删除演员将会发生什么


如果((TBUF_SIZE - (t_in - t_out))< = 2)


并尝试在''的情况下对此进行评估t_in''小于''t_out''。积分

促销发生并假设't_in - t_out''使用签名类型''int''的

边界进行评估。例如,假设我们得到-1作为结果。现在,

是时候从''TBUF_SIZE'中减去结果了。由于''TBUF_SIZE''具有较大的无符号类型,因此整个表达式在

无符号类型的范围内进行求值,这意味着-1被转换为首先是usigned类型。在

这种情况​​下-1变成一个大的无符号值。当我们从256减去那个大的无符号值时,我们会遇到环绕行为,最后的结果看起来好像我们实际上从256减去了-1,即我们得到257.

''如果'条件不满意。


现在,考虑与演员相同


if((TBUF_SIZE - (unsigned char)(t_in - t_out))< = 2)


第一个减法仍然给我们签名的值-1。但后来我们明确地将
转换为''unsigned char'',(假设8位字符)给我们255.

从''TBUF_SIZE'减去'会给我们1.现在''if'的条件

是满意的。


以上描述了代码行为时的两种可能情况使用

强制转换与不带强制转换的代码不同。这就是可能发生的事情。


-

投注,

Andrey Tarasevich



Question

should this cast be necessary?
The Compiler is 8 Bits the ints are 16 bits.
The Code is for a ring buffer

It does not work without the cast in this compiler.
I have seen it work else where without it.
Which way is right (or should it matter at all?)

Thanks Neil



unsigned char t_in;
unsigned char t_out;

/*----------------------------------------------------------------*/
bit com_putchar (unsigned char c)
{

/*If the buffer is full, return an error value.*/
if ((TBUF_SIZE - (unsigned char)(t_in - t_out)) <= 2)
return (1);

/* More Code */
/* More Code */
/* More Code */
/* More Code */

return (0);
}

解决方案

Neil <Ne*******@worldnet.att.netwrites:

Question

should this cast be necessary?
The Compiler is 8 Bits the ints are 16 bits.

I don''t know what you mean by "The Compiler is 8 Bits". I''ll assume
char is 8 bits (CHAR_BIT==8) and sizeof(int)==2.

The Code is for a ring buffer

It does not work without the cast in this compiler.

It''s impossible to tell what you mean by "does not work". Does it
fail to compile? Does it give you different results than the ones you
expected? What did you expect, and what did you get?

I have seen it work else where without it.
Which way is right (or should it matter at all?)

[...]
..

unsigned char t_in;
unsigned char t_out;

/*----------------------------------------------------------------*/
bit com_putchar (unsigned char c)

Presumably "bit" is declared somewhere.

{

/*If the buffer is full, return an error value.*/
if ((TBUF_SIZE - (unsigned char)(t_in - t_out)) <= 2)

Likewise TBUF_SIZE.

In an expression, any subexpression of type unsigned char is going to
be promoted to either int or unsigned int. It will be promoted to int
if int can hold all possible values of type unsigned char (which is
almost always the case).

So t_in - t_out is of type int, and it could be either positive,
negative, or zero. The conversion to unsigned char yields a positive
or zero result. For example, if t_in - t_out is -1, the conversion
probably yields 255.

You then subtract that result from TBUF_SIZE, but we have no idea of
the value, or even the type, of TBUF_SIZE.

That''s about all I can tell you.

return (1);

/* More Code */

[...]

>
return (0);
}

A minor style point: The parentheses on the return statements are not
necessary. They''re harmless, but I (and, I think, most c programers)
prefer:
return 1;
...
return 0;

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.


Keith Thompson wrote:

Neil <Ne*******@worldnet.att.netwrites:

>Question

should this cast be necessary?
The Compiler is 8 Bits the ints are 16 bits.


I don''t know what you mean by "The Compiler is 8 Bits". I''ll assume
char is 8 bits (CHAR_BIT==8) and sizeof(int)==2.

>The Code is for a ring buffer

It does not work without the cast in this compiler.


It''s impossible to tell what you mean by "does not work". Does it
fail to compile? Does it give you different results than the ones you
expected? What did you expect, and what did you get?

>I have seen it work else where without it.
Which way is right (or should it matter at all?)

[...]
.

>unsigned char t_in;
unsigned char t_out;

/*----------------------------------------------------------------*/
bit com_putchar (unsigned char c)


Presumably "bit" is declared somewhere.

>{

/*If the buffer is full, return an error value.*/
if ((TBUF_SIZE - (unsigned char)(t_in - t_out)) <= 2)


Likewise TBUF_SIZE.

In an expression, any subexpression of type unsigned char is going to
be promoted to either int or unsigned int. It will be promoted to int
if int can hold all possible values of type unsigned char (which is
almost always the case).

So t_in - t_out is of type int, and it could be either positive,
negative, or zero. The conversion to unsigned char yields a positive
or zero result. For example, if t_in - t_out is -1, the conversion
probably yields 255.

You then subtract that result from TBUF_SIZE, but we have no idea of
the value, or even the type, of TBUF_SIZE.

That''s about all I can tell you.

> return (1);

/* More Code */

[...]

> return (0);
}


A minor style point: The parentheses on the return statements are not
necessary. They''re harmless, but I (and, I think, most c programers)
prefer:
return 1;
...
return 0;

Sorry I was Not complete:
8 bit as in PIC16 CPU not a PC. 8 bit char and 16 bit ints
bit is actually a bit, but I assume it does not matter.

TBUF_SIZE Assume 32 for this purpose.

The parentheses I try to keep the code uniform. the original must have
had them.

Does not work means compiles, but does not work as expected. The math
does not work as the ring buffer wraps. The full buffer is not detected
and the data is over written.

So it could be an integer promotion issue (that would make sense in this
case). The one other Compiler has a none standard No promote option.
And the second was for a 32 bit compiler using unsigned longs

I hate fix something without understanding the fix, or complain about
the compiler when it doing the right thing. I could look at it again
and see if the compiler matches the math if it is all promoted.


Neil wrote:

...

>> /*If the buffer is full, return an error value.*/
if ((TBUF_SIZE - (unsigned char)(t_in - t_out)) <= 2)

...

You still forgot to mention one important detail: what is the _type_ of ''TBUF_SIZE''?

Let''s assume that ''TBUF_SIZE'' has a relatively "large" unsigned type. For
example, let''s assume that ''TBUF_SIZE'' is of type ''size_t''. Let''s also assume
that ''TBUF_SIZE''s value is equal to 256.

Now, consider what will happen if we remove the cast

if ((TBUF_SIZE - (t_in - t_out)) <= 2)

and try to evaluate this in situation when ''t_in'' is less than ''t_out''. Integral
promotion takes place and assume the ''t_in - t_out'' is evaluated withing the
bounds of signed type ''int''. Let say we get -1 as the result, for example. Now,
it''s time to subtract the result from ''TBUF_SIZE''. Since ''TBUF_SIZE'' is of large
unsigned type, the whole expression is evaluated within the bounds of that
unsigned type, meaning that the -1 is converted to that usigned type first. In
this case -1 turns into a large unsigned value. When we subtract that large
unsigned value from 256 we run into the wrap-around behavior and the final
result looks as if we in fact subtracted -1 from 256, i.e. we get 257. The
''if''s condition is not satisfied.

Now, consider the same with the cast

if ((TBUF_SIZE - (unsigned char)(t_in - t_out)) <= 2)

The first subtraction still gives us signed valuue -1. But then we explicitly
convert it to ''unsigned char'', which (assuming 8-bit chars) gives us 255. The
following subtraction from ''TBUF_SIZE'' will give us 1. Now the ''if''s condition
is satisfied.

The above desribes two possible scenarios when the behavior of the code with the
cast is different from that of the code without the cast. That''s what might happen.

--
Bets regards,
Andrey Tarasevich


这篇关于为什么这个演员是必要的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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