行输入和实现定义的行为 [英] Line input and implementation-defined behaviour

查看:68
本文介绍了行输入和实现定义的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

K& R book和Steve Summit的教程定义了一个getline()函数

正确测试getchar()对EOF的返回值。


我知道getchar()返回EOF或者字符值转换为

unsigned char。


因为char可能被签名(如果是的话, getchar()的返回值

超出其范围),以下代码中的注释行不是

产生实现定义的行为吗?

char s [SIZE];

int c;

size_t i = 0;


while((c = getchar())!= EOF&& c!=''\ n''&& i< SIZE - 1){

s [i] = c; / * ??? * /

i ++;

}


s [i] =''\ 0'';


如果这确实是实现定义的,有什么解决方案吗?


-

Enrico`Trippo''Porreca

Both K&R book and Steve Summit''s tutorial define a getline() function
correctly testing the return value of getchar() against EOF.

I know that getchar() returns EOF or the character value cast to
unsigned char.

Since char may be signed (and if so, the return value of getchar() would
be outside its range), doesn''t the commented line in the following code
produce implementation-defined behaviour?

char s[SIZE];
int c;
size_t i = 0;

while ((c = getchar()) != EOF && c != ''\n'' && i < SIZE - 1) {
s[i] = c; /* ??? */
i++;
}

s[i] = ''\0'';

If this is indeed implementation defined, is there any solution?

--
Enrico `Trippo'' Porreca

推荐答案

" Enrico`Trippo''Porreca" < TR **** @ lombardiacom.it>写道:
"Enrico `Trippo'' Porreca" <tr****@lombardiacom.it> wrote:
因为char可能被签名(如果是这样,getchar()的返回值将超出其范围),不是
以下代码产生实现定义的行为?


差不多。如果读取的字符的代码超出了

signed char的范围,则会生成实现定义的结果,或者引发实现定义的

信号。这并不像实现定义的行为那么糟糕,但差不多。

char s [SIZE];
int c;
size_t i = 0;

while((c = getchar())!= EOF&& c!=''\ n''&& i< SIZE - 1){
s [i] = c; / * ??? * /
i ++;
}

s [i] =''\''';

如果这确实是实现定义,是有什么解决方案吗?
Since char may be signed (and if so, the return value of getchar()
would be outside its range), doesn''t the commented line in the
following code produce implementation-defined behaviour?
Almost. If a character is read whose code is out of the range of
signed char, it produces an implementation-defined result, or an
implementation-defined signal is raised. This is not quite as bad
as implementation-defined behaviour, but almost.
char s[SIZE];
int c;
size_t i = 0;

while ((c = getchar()) != EOF && c != ''\n'' && i < SIZE - 1) {
s[i] = c; /* ??? */
i++;
}

s[i] = ''\0'';

If this is indeed implementation defined, is there any solution?




如果char已签名,并且该字符的值超出了

范围的signed char,那么你有超出范围转换为

a有符号整数类型,因此:结果是实现定义的

或实现定义的信号被引发。 (C99 6.3.1.3#3)


但是,因为这是现有C代码中非常常见的操作,所以实现者绝对会愚蠢到

定义这个有任何不良影响。


-

Simon。



If char is signed, and the value of the character is outside the
range of signed char, then you have an out-of-range conversion to
a signed integer type, so: "either the result is implementation-defined
or an implementation-defined signal is raised." (C99 6.3.1.3#3)

However, because this is such an incredibly common operation in
existing C code, an implementor would be absolutely idiotic to
define this to have any undesired effects.

--
Simon.


Simon Biber写道:
Simon Biber wrote:
char s [SIZE];
int c;
size_t i = 0;

while((c = getchar())!= EOF&& c!=''\ n''&& i< SIZE - 1){
s [i ] = c; / * ??? * /
i ++;
}

s [i] =''\''';

如果这确实是实现定义,是有什么解决方案吗?
char s[SIZE];
int c;
size_t i = 0;

while ((c = getchar()) != EOF && c != ''\n'' && i < SIZE - 1) {
s[i] = c; /* ??? */
i++;
}

s[i] = ''\0'';

If this is indeed implementation defined, is there any solution?



如果char已签名,并且该字符的值超出了
范围的signed char,那么你有一个超出范围的转换
有符号整数类型,因此:结果是实现定义的
或者引发实现定义的信号。 (C99 6.3.1.3#3)

然而,因为在现有的C代码中这是一个非常常见的操作,实现者绝对会愚蠢地定义这个任何不受欢迎的影响。



If char is signed, and the value of the character is outside the
range of signed char, then you have an out-of-range conversion to
a signed integer type, so: "either the result is implementation-defined
or an implementation-defined signal is raised." (C99 6.3.1.3#3)

However, because this is such an incredibly common operation in
existing C code, an implementor would be absolutely idiotic to
define this to have any undesired effects.




我同意,但AFAIK的实施者被允许是白痴......

我是对的吗?

以下是一个合理的解决方案(即没有任何陷阱

表示或类型转换或某些定义的行为问题)?


char s [SIZE];

unsigned char * t =(unsigned char *)s;

int c;

size_t i = 0;


while((c = getchar())!= EOF&& c!=''\ n''&& i< SIZE - 1 ){

t [i] = c; / * ??? * /

i ++;

}


s [i] =''\ 0'';
< br $>
-

Enrico`Trippo''Porreca



I agree, but AFAIK the implementor is allowed to be idiot...
Am I right?

Is the following a plausible solution (i.e. without any trap
representation or type conversion or something-defined behaviour problem)?

char s[SIZE];
unsigned char *t = (unsigned char *) s;
int c;
size_t i = 0;

while ((c = getchar()) != EOF && c != ''\n'' && i < SIZE - 1) {
t[i] = c; /* ??? */
i++;
}

s[i] = ''\0'';

--
Enrico `Trippo'' Porreca


" Enrico`Trippo''Porreca" ; < TR **** @ lombardiacom.it>写道:
"Enrico `Trippo'' Porreca" <tr****@lombardiacom.it> wrote:
我同意,但AFAIK的实施者被允许是白痴...
我是对的吗?


是的,但请相信我,任何犯了char< - > int转换

的人都会破坏大部分被视为

是完全可移植的。因此他们的实施将不会出售。

考虑< ctype.h>函数,要求输入是一个int,其值在unsigned char范围内。那是

为什么我们建议人们像这样投射到unsigned char:

char * p,s [] =" hello";

for(p = s; * p; p ++)

* p = toupper((unsigned char)* p);

现在如果* p的值为负数,现在转换为无符号

char时,它是正数且超出signed char范围。所以理论上这个理论上可以超出int的范围,如果int和signed

char具有相同的范围。因此你有相同的情况在

反向 - 无符号char到int转换不保证在范围内是



以下是a合理的解决方案(即没有任何陷阱表示或类型转换或某种定义的行为问题)?

char s [SIZE];
unsigned char * t = (unsigned char *)s;
int c;
size_t i = 0;

while((c = getchar())!= EOF&& c!= ''\\ n'&& i< SIZE - 1){
t [i] = c; / * ??? * /


赋值本身是安全的,但是因为它将任意的

表示放入数组的元素中,这是char

对象并且可能签名,它可能会生成陷阱

表示。那就是如果签名的char可以有陷阱

表示。我不太确定。

i ++;
}
s [i] =''\ 0'';
I agree, but AFAIK the implementor is allowed to be idiot...
Am I right?
Yes, but trust me, anyone who fouled up the char<->int conversion
would break a large proportion of existing code that is considered
to be completely portable. Therefore their implementation would
not sell.

Consider the <ctype.h> functions, which require that the input is
an int whose value is within the range of unsigned char. That is
why we suggest that people cast to unsigned char like this:
char *p, s[] = "hello";
for(p = s; *p; p++)
*p = toupper((unsigned char)*p);
Now if the value of *p was negative, now when converted to unsigned
char it is positive and outside the range of signed char. So this
could theoretically be outside the range of int, if int and signed
char have the same range. Therefore you have the same situation in
reverse - unsigned char to int conversion is not guaranteed to be
within range.
Is the following a plausible solution (i.e. without any trap
representation or type conversion or something-defined behaviour
problem)?

char s[SIZE];
unsigned char *t = (unsigned char *) s;
int c;
size_t i = 0;

while ((c = getchar()) != EOF && c != ''\n'' && i < SIZE - 1) {
t[i] = c; /* ??? */
The assignment itself is safe, but since it places an arbitrary
representation into the elements of the array s, which are char
objects and possibly signed, it might generate a trap
representation. That is if signed char can have trap
representations. I''m not completely sure.
i++;
}

s[i] = ''\0'';




-

西蒙。



--
Simon.


这篇关于行输入和实现定义的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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