program output?

B

bnp

Hi,

I took a test on C.
there was an objective question for program output type.
following is the program:

main()
{
char ch;
int i =2;
for (ch=0;ch<128;ch++)
i+=2;
printf("%d",i);
}
i wrote the answer 256 will be printed.
But our instructor told me that it will be infinite loop.
Is that right, I am not sure of the answer.

Regards,

Bhavik
 
L

Leor Zolman

Hi,

I took a test on C.
there was an objective question for program output type.
following is the program:

main()
{
char ch;
int i =2;
for (ch=0;ch<128;ch++)
i+=2;
printf("%d",i);
}
i wrote the answer 256 will be printed.
But our instructor told me that it will be infinite loop.
Is that right, I am not sure of the answer.

Kinda tricky.
First of all, the default "signedness" of the char type is
platform-dependent. If it is 8 bits and "signed", as is the default on
typical PC-based platforms, then this does indeed go into an infinite loop.
In that case, the range of values for an 8-bit char is -128 to +127. It
will always be less than +128.

If the default for chars is unsigned, then the program output is 258 [I
didn't figure it out, I just ran it ;-) ]
-leor
 
P

Pieter Droogendijk

Hi,

I took a test on C.
there was an objective question for program output type.
following is the program:

main()

int main () or int main (void) is preferred.

Proper indentation is a Good Thing(tm), even for trivial examples such as
this.
char ch;
int i =2;
for (ch=0;ch<128;ch++)
i+=2;
printf("%d",i);
}
i wrote the answer 256 will be printed.
But our instructor told me that it will be infinite loop.
Is that right, I am not sure of the answer.

Your instructor may have been right. It all depends on CHAR_MAX, which may
be 127 if char is signed. If this is the case, ch will never be >= 128,
and the loop will never end. If CHAR_MAX is greater than 127 (because it's
unsigned, or because char has more than 8 value bits), then it may print
258 (and will for sure if you print a newline or flush stdout).
 
A

Arthur J. O'Dwyer

I took a test on C.
there was an objective question for program output type.
following is the program:



main()

_int_ main() required for C99; _int_ main(_void_) preferred in both
C89 and C99. (Where _this_ indicates emphasis, not literal underscores.)
{
char ch;

Lack of indentation is a bad thing and should be avoided, especially
on Usenet and on school tests. Also, everywhere else.
int i =2;
for (ch=0;ch<128;ch++)

Non-strict-conformance: program behavior depends on signedness of
plain char.
Possible undefined behavior: If char is signed and has eight bits,
signed integer overflow will occur.
i+=2;
printf("%d",i);

Possible linker error: 'printf' undefined.
Undefined behavior: variadic function 'printf' called without
prototype in scope.
Constraint violation (is that correct?): program output ends
without terminating newline '\n'.
}
i wrote the answer 256 will be printed.
But our instructor told me that it will be infinite loop.
Is that right, I am not sure of the answer.

Yes, you are both "right." Only the program is wrong.

-Arthur
 
C

CBFalconer

Pieter said:
int main () or int main (void) is preferred.


Proper indentation is a Good Thing(tm), even for trivial examples
such as this.


Your instructor may have been right. It all depends on CHAR_MAX,
which may be 127 if char is signed. If this is the case, ch will
never be >= 128, and the loop will never end. If CHAR_MAX is
greater than 127 (because it's unsigned, or because char has
more than 8 value bits), then it may print 258 (and will for
sure if you print a newline or flush stdout).

No, in that (signed) case you will overflow ch, and behaviour
becomes undefined. So it may well print "the instructor is full
of it" or do anything else.
 
B

buda

So overflow is undefined? I thought that the "overflowed bit" gets discarded
and you end up with the "next" number, which in this case might be -128 (if
char is 8 bits signed, then gets to 127 which is 0111 1111, thus adding one
in binary will make it 1000 0000 which translates into -128). I actually
expect this to be "not defined" by the standard, but this is the behavior on
most (if not all) machines I have seen.
 
D

Dan Pop

In said:
Kinda tricky.

Not really: the code invokes undefined behaviour at least once, by calling
printf without a proper declaration in scope, so it is not even worth
analysing it: anything can legally happen.
First of all, the default "signedness" of the char type is
platform-dependent. If it is 8 bits and "signed", as is the default on
typical PC-based platforms, then this does indeed go into an infinite loop.

Can we have a chapter and verse for that? I naively thought that signed
overflow results in undefined behaviour...
In that case, the range of values for an 8-bit char is -128 to +127.

Can we have a chapter and verse for that? I naively thought that the
standard only guaranteed -127 to 127 and that sign-magnitude and one's
complement implementations are perfectly OK...
It will always be less than +128.

True, but by the time it makes the transition from 127 to whatever value
(if any), anything can happen... including getting out of the loop.
If the default for chars is unsigned, then the program output is 258 [I
didn't figure it out, I just ran it ;-) ]

Maybe, maybe not. As the last line of output is not newline terminated,
there is no guarantee that the program will produce any output at all
(it's an implementation-defined feature).

Whoever wrote this test expecting another answer than "undefined
behaviour" should better start learning C...

Here's a properly rewritten version of this test:

Assuming 8-bit bytes, what is the output of the following program?

#include <stdio.h>

int main()
{
unsigned char ch;
unsigned int i = 2;

for (ch = 0; ch < 256; ch++) i += 2;
printf("%u\n", i);
return 0;
}

Note that if i is plain int, signed overflow will occur inside the
infinite loop, and all the bets are off, again.

Dan
 
R

Ralmin

buda said:
So overflow is undefined? I thought that the "overflowed bit" gets
discarded and you end up with the "next" number, which in this case
might be -128 (if char is 8 bits signed, then gets to 127 which is
0111 1111, thus adding one in binary will make it 1000 0000 which
translates into -128). I actually expect this to be "not defined"
by the standard, but this is the behavior on most (if not all)
machines I have seen.

Yes, signed integer overflow is undefined behaviour in C. Some machines trap
on overflow, others discard the overflow like you describe. In that case it
depends on whether the signed integer is using 2's complement, 1's
complement or the signed magnitude system.

In 8-bit 2's complement, 1000 0000 is -128
In 8-bit 1's complement, 1000 0000 is -127
In 8-bit signed magnitude, 1000 0000 is negative zero, which might be a
valid result, or might itself be a trap representation.

There might even be more wacky forms of undefined behaviour that occur on
overflow.
 
M

Martin Dickopp

Arthur J. O'Dwyer said:
Constraint violation (is that correct?): program output ends
without terminating newline '\n'.

Implementation-defined and possibly undefined behavior. See 7.19.2#2:
"A text stream is an ordered sequence of characters composed into lines,
each line consisting of zero or more characters plus a terminating new-
line character. Whether the last line requires a terminating new-line
character is implementation-defined. [...]"

Martin
 
B

buda

Ralmin said:
Yes, signed integer overflow is undefined behaviour in C. Some machines trap
on overflow, others discard the overflow like you describe. In that case it
depends on whether the signed integer is using 2's complement, 1's
complement or the signed magnitude system.

In 8-bit 2's complement, 1000 0000 is -128
In 8-bit 1's complement, 1000 0000 is -127
In 8-bit signed magnitude, 1000 0000 is negative zero, which might be a
valid result, or might itself be a trap representation.

There might even be more wacky forms of undefined behaviour that occur on
overflow.

Thanks for the answer.
 
C

CBFalconer

*** Rude top-posting fixed ***
So overflow is undefined? I thought that the "overflowed bit" gets
discarded and you end up with the "next" number, which in this
case might be -128 (if char is 8 bits signed, then gets to 127
which is 0111 1111, thus adding one in binary will make it 1000
0000 which translates into -128). I actually expect this to be
"not defined" by the standard, but this is the behavior on most
(if not all) machines I have seen.

Undefined for signed quantities. Defined for unsigned ones. This
is all spelled out in the standard, so there is no need to guess.
Your description is only one form undefined behaviour may take.
Undefined behaviour could also be for the machine to post spam
offering large rewards for the assasination of top-posters.
 
E

Emmanuel Delahaye

In said:
I took a test on C.
there was an objective question for program output type.
following is the program:

This program invokes an undefined behaviour. For many reasons, its output is
not predictable.

Here are my comments.

/* -ed- Missing fot printf() (mandatory) */
#include <stdio.h>

int main ()
{
/* -ed- 128 is not guaranteed to fit into a char.
* It fits into an unsigned char.
*/
unsigned char ch;
int i = 2;

for (ch = 0; ch < 128; ch++)
{
i += 2;
}
/* -ed- Curly brackets added for safety and look. */

/* -ed- '\n' added to be sure to see the output.*/
printf ("%d\n", i);

/* -ed- Because main() returns an int */
return 0;
}

Once fixed, the result is 2 + 128 * 2 = 258.
 
L

Leor Zolman

Not really: the code invokes undefined behaviour at least once, by calling
printf without a proper declaration in scope, so it is not even worth
analysing it: anything can legally happen.

Sure, technically this (and all the rest of it) may be correct. I responded
from an exam question standpoint: "What will it do?" (IOW, "What does it do
for the instructor?"), rather than "What does the Standard say?" (applying
the usual rigor expected for answers to general questions in this group). I
should have prefaced my response accordingly.
-leor
 
A

Arthur J. O'Dwyer

Arthur J. O'Dwyer said:
Constraint violation (is that correct?): program output ends
without terminating newline '\n'.

Implementation-defined and possibly undefined behavior. See 7.19.2#2:
"A text stream is an ordered sequence of characters composed into lines,
each line consisting of zero or more characters plus a terminating new-
line character. Whether the last line requires a terminating new-line
character is implementation-defined. [...]"

Thanks for the quote. But what's the quote that tells us that if
we fail to do something that is, quote, "required," that we invoke
undefined behavior? I don't see anything relevant upon a quick scan
of Appendix J, either...

-Arthur
 
A

Arthur J. O'Dwyer

Sure, technically this (and all the rest of it) may be correct. I responded
from an exam question standpoint: "What will it do?" (IOW, "What does it do
for the instructor?"), rather than "What does the Standard say?" (applying
the usual rigor expected for answers to general questions in this group). I
should have prefaced my response accordingly.

However --- and I speak from personal experience at high school and
college levels --- it is almost always easier to prove to the instructor
that the code is faulty, than it is to try to guess what the instructor
was thinking.

In this case, the OP had two choices: write down what he thought the
instructor wanted, or raise his hand and say "Excuse me, there seems to
be a bug in this program... could you clarify the problem, please?"
Best case, the instructor realizes the problem is unsolvable and gives
everybody in the class extra credit. Worst case, the instructor says,
"char is unsigned and <stdio.h> is included," and the OP is back where
he started.
The OP had better have hoped for the best-case scenario, since his
guess turned out to be wrong. By drawing attention to the bugs in
the program, he would have maximized his chances of getting credit for
the question.

Again, I speak from experience, and am not being pedantic merely
for pedantry's sake. If the OP can learn to recognize common errors
in C programs, then he stands to benefit in the short term. (In the
long term, he won't be dealing with contrived C programs anymore, and
he'll have to learn common *correct* ways to *write* C programs. But
this is a good way to start. :)

-Arthur
 
O

Old Wolf

I took a test on C.
there was an objective question for program output type.
following is the program:

main()
{
char ch;
int i =2;
for (ch=0;ch<128;ch++)
i+=2;
printf("%d",i);
}
i wrote the answer 256 will be printed.
But our instructor told me that it will be infinite loop.
Is that right, I am not sure of the answer.
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Good work. Since the behaviour is undefined (if CHAR_MAX is 127),
it is not possible to be sure of the answer.
 
M

Martin Dickopp

Arthur J. O'Dwyer said:
Arthur J. O'Dwyer said:
Constraint violation (is that correct?): program output ends
without terminating newline '\n'.

Implementation-defined and possibly undefined behavior. See 7.19.2#2:
"A text stream is an ordered sequence of characters composed into lines,
each line consisting of zero or more characters plus a terminating new-
line character. Whether the last line requires a terminating new-line
character is implementation-defined. [...]"

Thanks for the quote. But what's the quote that tells us that if
we fail to do something that is, quote, "required," that we invoke
undefined behavior?

Assuming the case that the implementation requires a terminating newline
character, the standard doesn't say what should happen if there is no
such character. Therefore, the behavior is undefined since it is not
explicitly defined, as per 4#2: "[...] Undefined behavior is otherwise
indicated in this International Standard [...] by the omission of any
explicit definition of behavior. [...]"

(That's at least how I understand 7.19.2#2.)

AFAIKT, the term "require" isn't explicitly defined in the standard, so
I understand it in its normal English sense (i.e. unlike a "constraint
violation", a "requirement violation" has no special meaning).

Martin
 
L

Leor Zolman

However --- and I speak from personal experience at high school and
college levels --- it is almost always easier to prove to the instructor
that the code is faulty, than it is to try to guess what the instructor
was thinking.

<OT>
I'm tempted to change the subject now to "[OT]: Challenging instructors" or
something. This could be an interesting topic, but it seems pretty OT.
In this case, the OP had two choices: write down what he thought the
instructor wanted, or raise his hand and say "Excuse me, there seems to
be a bug in this program... could you clarify the problem, please?"

If the OP knew there was a bug. But the question he posted was about what
the program would do. How many students, in that position, and with an
instructor who writes exam questions like /that/ (the declaration of main
was, IMO, particularly egregious), would be likely to detect a "flaw" in
the question? To be able to ask, you have to have a handle on what to ask.
From what I see, the most likely question to come up in this example would
have been regarding the signed-ness of char. I would /hope/ the fact that
this is implementation-dependent would have been discussed in class, but I
wouldn't bet on it. Given that, I'd put the chances near zero that there
was any discussion in that course about how not including <stdio.h> invokes
UB with printf (I can't even say I fully understand that myself right now),
or what happens when the last line of output is unterminated. Unless they'd
had access to a C99 compiler in strict mode, I doubt these issues would
have shown up even if they'd been written into programs.

I get the feeling that if someone /did/ bring up the stdio.h or line
termination issue, the instructor either wouldn't know what the student was
talking about, or brush it off with a roll of the eyes and a "Just
assume...."
Best case, the instructor realizes the problem is unsolvable and gives
everybody in the class extra credit. Worst case, the instructor says,
"char is unsigned and <stdio.h> is included," and the OP is back where
he started.
The OP had better have hoped for the best-case scenario, since his
guess turned out to be wrong. By drawing attention to the bugs in
the program, he would have maximized his chances of getting credit for
the question.

A good instructor loves to be corrected and/or challenged by students, but
I've (unfortunately) also seen some that it would have been a grievous
tactical error to point out some of those issues to. Unfortunately, those
latter types often tend to have a disproportional amount of political clout
in the learning institution, for some Godforsaken reason...
Again, I speak from experience, and am not being pedantic merely
for pedantry's sake. If the OP can learn to recognize common errors
in C programs, then he stands to benefit in the short term. (In the
long term, he won't be dealing with contrived C programs anymore, and
he'll have to learn common *correct* ways to *write* C programs. But
this is a good way to start. :)

Reading this newsgroup could definitely accelerate one's coming-of-age as a
C programmer (though perhaps not as much as posting and then being brave
enough to actually read the responses). At the beginning level, however, I
suspect most students' neurons are busy enough trying to remember how to
define and use pointers, stay within array bounds, understand flow control,
and (with the especially clueless instructors) memorizing the precedence
table, to have the capacity left to pursue distinctions of UB between
signed and unsigned integral values. The ones who do, are probably destined
to be future regulars in this group ;-)
-leor
 
J

Jack Klein

Arthur J. O'Dwyer said:
Constraint violation (is that correct?): program output ends
without terminating newline '\n'.

Implementation-defined and possibly undefined behavior. See 7.19.2#2:
"A text stream is an ordered sequence of characters composed into lines,
each line consisting of zero or more characters plus a terminating new-
line character. Whether the last line requires a terminating new-line
character is implementation-defined. [...]"

Thanks for the quote. But what's the quote that tells us that if
we fail to do something that is, quote, "required," that we invoke
undefined behavior?

Assuming the case that the implementation requires a terminating newline
character, the standard doesn't say what should happen if there is no
such character. Therefore, the behavior is undefined since it is not
explicitly defined, as per 4#2: "[...] Undefined behavior is otherwise
indicated in this International Standard [...] by the omission of any
explicit definition of behavior. [...]"

(That's at least how I understand 7.19.2#2.)

AFAIKT, the term "require" isn't explicitly defined in the standard, so
I understand it in its normal English sense (i.e. unlike a "constraint
violation", a "requirement violation" has no special meaning).

Martin

Anything that the standard specifies as "implementation-defined", a
term which is precisely defined in the standard, cannot result in
undefined behavior.

The implementation is required to select one of the available choices,
in this case either the last line appears in the output stream if no
terminating new-line is present, or it does not. And the
implementation is required to document its choice, therefore defining
the behavior for that implementation.
 
M

Martin Dickopp

Jack Klein said:
Arthur J. O'Dwyer said:
On Mon, 24 May 2004, Martin Dickopp wrote:


Constraint violation (is that correct?): program output ends
without terminating newline '\n'.

Implementation-defined and possibly undefined behavior. See 7.19.2#2:
"A text stream is an ordered sequence of characters composed into lines,
each line consisting of zero or more characters plus a terminating new-
line character. Whether the last line requires a terminating new-line
character is implementation-defined. [...]"

Thanks for the quote. But what's the quote that tells us that if
we fail to do something that is, quote, "required," that we invoke
undefined behavior?

Assuming the case that the implementation requires a terminating newline
character, the standard doesn't say what should happen if there is no
such character. Therefore, the behavior is undefined since it is not
explicitly defined, as per 4#2: "[...] Undefined behavior is otherwise
indicated in this International Standard [...] by the omission of any
explicit definition of behavior. [...]"

(That's at least how I understand 7.19.2#2.)

AFAIKT, the term "require" isn't explicitly defined in the standard, so
I understand it in its normal English sense (i.e. unlike a "constraint
violation", a "requirement violation" has no special meaning).

Anything that the standard specifies as "implementation-defined", a
term which is precisely defined in the standard, cannot result in
undefined behavior.

The implementation is required to select one of the available choices,
in this case either the last line appears in the output stream if no
terminating new-line is present, or it does not. And the
implementation is required to document its choice, therefore defining
the behavior for that implementation.

Let's assume an implementation that has documented that the last line
requires a terminating newline character. On such an implementation,
the following program is not correct:

#include <stdio.h>
int main (void) { putchar ('x'); return 0; }

I would have thought the behavior of the program is undefined on such an
implementation. If that is not the case, what is the behavior of the
above program on such an implementation?

Martin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,608
Members
45,241
Latest member
Lisa1997

Latest Threads

Top