www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1995/05/03/09:19:04

Date: Wed, 3 May 1995 19:31:51 +0900
From: Stephen Turnbull <turnbull AT shako DOT sk DOT tsukuba DOT ac DOT jp>
To: eliz AT is DOT elta DOT co DOT il
Cc: A DOT APPLEYARD AT fs2 DOT mt DOT umist DOT ac DOT uk, DJGPP AT SUN DOT SOE DOT CLARKSON DOT EDU
Subject: Bad bug with for(-;-;-) and an enum name

I knew I shoulda posted last night....  Abusing a guy for cutting his
code done to where it exhibits the bug in minimal fashion 'cause you
can't see how he'd find code like that useful is not on, hey?

Aside to Mr. Appleyard:  If you haven't reported it yet, you might
want to add some of the info below to your report and send it to
'bug-g++@prep.ai.mit.edu'.

Eli quotes A.APPLEYARD
   > #include<stdio.h>
   > enum{q=1,imax=256};
   > main(){double x,y; int i,j,k,l,im=imax;
   > printf("A: "); for(i=-im  ;i<im  ;i++) printf("%d ",i); printf("\n");
   > printf("B: "); for(i=-imax;i<imax;i++) printf("%d ",i); printf("\n");}
   >
   > When this Gnu C++ program runs, loop A prints consecutive numbers
   > on screen as expected, but loop B prints <<no numbers at all>>.

and then thusly admonishes:

   You are getting punished for grossly misusing (IMHO) the enum facility.

Aaron doesn't say "grossly" but he didn't like it either.  More Eli:

   This facility exists with the sole purpose of declaring variables which
   can accept only a certain number of discrete values.  In your case, you
   told the compiler *explicitly* that the *only* value it can accept is
   256.  So don't be mad when the compiler finds it appropriate to
   implement imax as an unsigned int (or unsigned short), which means that

sizeof(imax) == 4 under both DJGPP (g++ 2.6.3) and linux (g++ 2.5.8),
and the latter also exhibits the funky loop behavior.  I also checked
other values and variable names under DJGPP only.  For enumerations
with all enumerators positive, the incorrect behavior doesn't change.
If either imax or q is negative, the program behaves as Appleyard
expected.  Finally, it behaves "correctly" when compiled as C code
under DJGPP gcc 2.6.3.

   -imax isn't less than imax, and the loop never executes.  If you still
   want to write your program with enums, you should explicitly cast it to
   int *before* negating.

Eli suggested -Wall.  GCC does not mention the enumerator, but does
harrass me about the 'printf("size = %d\n",sizeof(imax))' statement I
added (sizeof is a long int) and complain about the unused variables.

At least according to the ARM (1990), G++ is just plain wrong.
Heeeeeere's Bjarne:

"The 'signed' specifier ... is redundant with [non-char, non-bitfield]
 integral types [including enums]." (p. 111)
"The value of an enumerator must be an 'int' or a value that can be
 promoted to 'int' by integral promotion." (p. 113)
"Appearances to the contrary, there are no operations (except
 assignment) defined on enumerations; variables and constants of
 enumeration types are converted to integers before arithmetic
 [including negation] is done." (p.114)

I couldn't find anything in the Info file that directly said anything
about the unsigned issue, but there is one option -fenum-int-equiv
which is described (under G++ options) as "Permit implicit conversion
of `int' to enumeration types.  Normally GNU C++ allows conversion of
`enum' to `int', but not the other way around."  This suggests that
GNU intends to follow the ARM on this.

Therefore, the ARM interpretation of Appleyard's code is

#include<stdio.h>                                                     
enum{q=1,imax=256};                                                   
main ()
{
    double x,y; int i,j,k,l,im=imax;                               
    printf("A: "); for(i=-im  ;i<im  ;i++) printf("%d ",i); printf("\n"); 
    printf("B: ");
    for (i = - (int) imax; i < (int) imax; i++)
        printf("%d ",i);
    printf("\n");
}

which code of course runs correctly, as Eli suggests.

As for abuse of enums, Aaron may be a little correct about anonymous
enums.  But I see nothing wrong with the following use of enums,
perhaps in a portable library for external searching and sorting:

enum optimal_buffer_size_onSystemX {
    // uncommenting this changes the semantics!  Yeech!
    // unbuffered =-1,
    small =512,
    big =65536
};

void iterate_over_buffer (char*, int);

void funkyfunc (void)
{
    optimal_buffer_size_onSystemX limit = small;
    char *buffer = (char*) malloc(limit);

    interate_over_buffer(buffer,limit);
}

This is one case where it is useful to be able to assign specific
values to enums and use them as ints.

-- 
Stephen Turnbull  /  Yaseppochi-gumi  /  <turnbull AT shako DOT sk DOT tsukuba DOT ac DOT jp>
http://turnbull.sk.tsukuba.ac.jp/      anon FTP: turnbull.sk.tsukuba.ac.jp
Check out Kansai-WWW, too ------------> http://pclsp2.kuicr.kyoto-u.ac.jp/

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019