Sender: vheyndri AT rug DOT ac DOT be Message-Id: <34E18CB9.5D9E@rug.ac.be> Date: Wed, 11 Feb 1998 12:34:17 +0100 From: Vik Heyndrickx Mime-Version: 1.0 To: Hans-Bernhard Broeker Cc: DJ Delorie , djgpp-workers AT delorie DOT com Subject: Re: char != unsigned char... sometimes, sigh References: Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Precedence: bulk Hans-Bernhard Broeker wrote: > > On Tue, 10 Feb 1998, Vik Heyndrickx wrote: > > > The following is an ANSI compliant behaving macro, and it supports also > > 'signed char' > > It yields reasonably efficient hard-code. > > > > #define isupper(c) ({int t=(c);unsigned v;\ > > ++t;\ > > if(t<0)t+=256;\ > > v=__dj_ctype_flags[t];\ > > (v&__dj_ISUPPER)!=0;}) > > Which brings me to an idea: why should we provide is* _macros_ at all? As > the DJGPP libc is for gcc, anyway, why not use 'extern inline' functions > instead? That'd save all the special casing and whatnot, and automatically > turn it into a function call whenever gcc thinks that's the better idea... Why would this save us the special casing? > I.e., why not put *this* in inlines/ctype.ha: > > extern int isupper(int c); > extern inline int isupper(int c) { > return __dj_ctype_flags[c+1]&__dj_ISUPPER; > } The macro's I offered were also acceptable. Every library I've seen so far (bo*nd, djgpp, FreeBSD, gnulibc) does offer a set of macro's. > > The following is an ANSI compliant behaving macro, it supports only > > 'unsigned char'. > > It yields the most efficient hard-code possible in many cases. > > > > #define isupper(c) ({int t=(c);unsigned v;\ > > ++t;\ > > v=__dj_ctype_flags[t];\ > > (v&__dj_ISUPPER)!=0;}) > > > > Note that ANY change you will make to these macro's will turn them less > > efficient. I know where I am talking about. > > Could you unclose some of that knowledge? Like: why should your solution > with two temporary variables be more efficient than a simple > > ((int)((__dj_ctype_flags[((int)(t))+1]&__dj_ISUPPER)) Because of the gnu c compiler optimization strategies. According to the manual, you can't just assign enough to temporary variables. If you have a look at the produced asm code, you will that this is correct. In this particular example you could as well write "v=__dj_ctype_flags[t+1]", but in the other (more fail safe) example I gave, this sequence is essential. Although, I must admit that 'eggs' does a better optimization, but that is not unexpected, is it? > And how could a comparison ('!=0' at the end of your code) be more > efficient than a simple cast to int? The is* functions aren't required to > return only 1 or 0, after all, so there's no real need to translate '!=0' > to 1. My proposal never yields worse code, and in case the user wants to assign the result from this macro to e.g. a char (for memory conservation) this will always work, something that cannot be said from your example. In case that I have two choices which offer equivalent efficient code, I always choose the safer solution. -- \ Vik /-_-_-_-_-_-_/ \___/ Heyndrickx / \ /-_-_-_-_-_-_/