[comp.lang.c] Strange Behavior?

pjh@mccc.edu (Peter J. Holsberg) (05/08/91)

Here is an extract from a program a student wrote.  Note that he has
declared "input" incorrectly.  The strange behavior is that, when choice
"1" is made, the print function outputs all but the first line that was
entered.  Can anyone explain that in terms of what scanf() is doing to
memory near "input"?  (This is on a 386, if endianism matters.)

Thanks.
==============================================================
#include <stdio.h> 
#include <string.h>

void print(char *point[], int num);

#define MAX 9
#define SIZE 80
#define RETURN ""

main()
{
   int i;
   int num = 0, return_value = 1;
   char sentence [MAX][SIZE];   /* an array of strings */
   char *point[MAX];            /* an array of pointers to char */
   char *orginal[MAX];          /* an array holding the orginal sequence */
   char input;	/* SHOULD HAVE BEEN int input!!!  */

   printf("Input up to ten sentences \n");
   while(gets(sentence[num]) != NULL && num < MAX 
	     && strcmp(sentence[num], RETURN) != 0) 
   {
      point[num] = orginal[num] = sentence[num];  
      num++;
   }

	printf("Make a choice: ");
	scanf ("%d" , &input);      /* value converted to decimal integer
					but stored "in" a char ???  */
      
      switch(input)
      {
         case 1:  print(orginal,num);
                  break;
         case 5:  return;
         default: printf("Unknown response \n");
       }
}

void print(char *pointer[], int num)
{
    int count;

    for (count = 0 ; count < num ; count++)
       puts(pointer[count]);
}
======================================

Pete
-- 
Prof. Peter J. Holsberg      Mercer County Community College
Voice: 609-586-4800          Engineering Technology, Computers and Math
UUCP:...!princeton!mccc!pjh  1200 Old Trenton Road, Trenton, NJ 08690
Internet: pjh@mccc.edu	     Trenton Computer Festival -- 4/20-21/91

ping@cubmol.bio.columbia.edu (Shiping Zhang) (05/09/91)

In article <1991May8.020720.20170@mccc.edu> pjh@mccc.edu (Peter J. Holsberg) writes:
>Here is an extract from a program a student wrote.  Note that he has
>declared "input" incorrectly.  The strange behavior is that, when choice
>"1" is made, the print function outputs all but the first line that was
>entered.  Can anyone explain that in terms of what scanf() is doing to
>memory near "input"?  (This is on a 386, if endianism matters.)
 
[...]

>   char sentence [MAX][SIZE];   /* an array of strings */
>   char *point[MAX];            /* an array of pointers to char */
>   char *orginal[MAX];          /* an array holding the orginal sequence */
>   char input;	/* SHOULD HAVE BEEN int input!!!  */
 
[...]
 
>	printf("Make a choice: ");
>	scanf ("%d" , &input);      /* value converted to decimal integer

I think it results from declaring input as char and using it as int
in scanf(). When scanf() writes 1 into the location of input, it puts
into 0's those bits that belong to the first byte(s) of sentence[0],
terminating sentence[0] at its first byte.  I could be wrong, though.

-ping

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (05/09/91)

In article <1991May8.020720.20170@mccc.edu>, pjh@mccc.edu (Peter J. Holsberg) writes:
> Here is an extract from a program a student wrote.

Holsberg pointed out that a variable was declared char rather than int.
In that program, on a little-endian machine, it will work; making the
behaviour of longer and shorter integers consistent is what little-endian
is _for_, after all.

> #define MAX 9

>    char sentence [MAX][SIZE];   /* an array of strings */

>    printf("Input up to ten sentences \n");

There is a contradiction here.  If sentence[] is to hold up to 10
sentences, MAX had better be 10, not 9!

The input loop would be better as
	#define MAX 10
	for (num = 0;
	     num < 10 && gets(sentence[num]) != NULL
		      && strcmp(sentence[num], "") != 0;
	     num++)
	    point[num] = original[num] = sentence[num];

Note: gets() has problems.  Best to avoid it.  See the FAQ.
-- 
Bad things happen periodically, and they're going to happen to somebody.
Why not you?					-- John Allen Paulos.

pjh@mccc.edu (Pete Holsberg) (05/09/91)

In article <1991May8.204009.1694@cubmol.bio.columbia.edu> ping@cubmol.bio.columbia.edu (Shiping Zhang) writes:
=In article <1991May8.020720.20170@mccc.edu> pjh@mccc.edu (Peter J. Holsberg) writes:
=>Here is an extract from a program a student wrote.  Note that he has
=>declared "input" incorrectly.  The strange behavior is that, when choice
=>"1" is made, the print function outputs all but the first line that was
=>entered.  Can anyone explain that in terms of what scanf() is doing to
=>memory near "input"?  (This is on a 386, if endianism matters.)
= 
=[...]
=
=>   char sentence [MAX][SIZE];   /* an array of strings */
=>   char *point[MAX];            /* an array of pointers to char */
=>   char *orginal[MAX];          /* an array holding the orginal sequence */
=>   char input;	/* SHOULD HAVE BEEN int input!!!  */
= 
=[...]
= 
=>	printf("Make a choice: ");
=>	scanf ("%d" , &input);      /* value converted to decimal integer
=
=I think it results from declaring input as char and using it as int
=in scanf(). When scanf() writes 1 into the location of input, it puts
=into 0's those bits that belong to the first byte(s) of sentence[0],
=terminating sentence[0] at its first byte.  I could be wrong, though.

I'm sure you're right.  But what I really want to know is why the
compiler assigns memory that way.  It would seem to me that it would
assign memory "downward," so that the attempt to write a 4 byte value
into a 1 byte location would result in the "corruption" of the 3 cells
*following* the one allocated to "input."

Pete
-- 
Prof. Peter J. Holsberg      Mercer County Community College
Voice: 609-586-4800          Engineering Technology, Computers and Math
UUCP:...!princeton!mccc!pjh  1200 Old Trenton Road, Trenton, NJ 08690
Internet: pjh@mccc.edu	     Trenton Computer Festival -- 4/20-21/91

ping@cubmol.bio.columbia.edu (Shiping Zhang) (05/10/91)

In article <1991May9.161425.17079@mccc.edu> pjh@mccc.edu (Pete Holsberg) writes:
<In article <1991May8.204009.1694@cubmol.bio.columbia.edu> ping@cubmol.bio.columbia.edu (Shiping Zhang) writes:
<=In article <1991May8.020720.20170@mccc.edu> pjh@mccc.edu (Peter J. Holsberg) writes:
<=>Here is an extract from a program a student wrote.  Note that he has
<=>declared "input" incorrectly.  The strange behavior is that, when choice
<=>"1" is made, the print function outputs all but the first line that was
<=>entered.  Can anyone explain that in terms of what scanf() is doing to
<=>memory near "input"?  (This is on a 386, if endianism matters.)
<=[...]
<=>   char sentence [MAX][SIZE];   /* an array of strings */
<=>   char *point[MAX];            /* an array of pointers to char */
<=>   char *orginal[MAX];          /* an array holding the orginal sequence */
<=>   char input;	/* SHOULD HAVE BEEN int input!!!  */
<= 
<=[...]
<= 
<=>	printf("Make a choice: ");
<=>	scanf ("%d" , &input);      /* value converted to decimal integer

<=I think it results from declaring input as char and using it as int
<=in scanf(). When scanf() writes 1 into the location of input, it puts
<=into 0's those bits that belong to the first byte(s) of sentence[0],
<=terminating sentence[0] at its first byte.  I could be wrong, though.
 
<I'm sure you're right.  But what I really want to know is why the
<compiler assigns memory that way.  It would seem to me that it would
<assign memory "downward," so that the attempt to write a 4 byte value
<into a 1 byte location would result in the "corruption" of the 3 cells
<*following* the one allocated to "input."
 
The memory space is allocated for those variables as a stack. The space
for a later declared varible is put on the top of the stack with a smaller
address. According to the order in which the variables are declared in this
case, the space for input is on the top. After all I might be wrong in my
previous post. In this case, it should be the pointer original[0] that is
corrupted, making it point to an invalid location. You can actually check the
location of those variables by printing out their addresses as in the following
code:

printf("sentence[0] %d, original[0] %d, input %d\n",
    (int) sentence, (int) original, (int) &input);

-ping