Topic : C Lessons
Author : Christopher Sawtell
Page : << Previous 10  Next >>
Go to page :


compatability mode. However a collegue, who
was using an old compiler, and I spent hours trying to find this strange bug!
The cure for the problem is either to put spaces on either side of the '=' sign
or to bracket the unary minus to the operand.

        a=(-2);
        a = -2;


Either is acceptable, and might save you a lot of spleen if sombody tries
to install your work of art program on an ancient machine.

  The other caution is the use of the shifting instructions with signed
and unsigned integers.

        If you shift a signed integer to the right when the sign bit is set
then in all probability the sign will be extended. Once again a little
demo program. Please cut it out of the news file with your editor
and play with it.

/* ----------------------------------------- */

#ident "#(@) shifts.c - Signed / Unsigned integer shifting demo."
#include <stdio.h>

#define WORD_SIZE ( sizeof ( INTEGER int ) * 8 )
#define NIBBLE_SIZE 4
#define NIBBLES_IN_WORD (( WORD_SIZE ) / NIBBLE_SIZE )
#define SIGN_BIT ( 1 << ( WORD_SIZE - 1 ))

char *title[] =
{ "       Signed             Unsigned",
        "                 Signed                                 Unsigned"
        };

main ()
{
        INTEGER int a;
        unsigned INTEGER int b, mask;
        int ab, i, j, bit_counter, line_counter;

        a = b = SIGN_BIT;
        printf ( "%s\n\n", title [ ( WORD_SIZE == 16 ) ? 0 : 1 ] );

        for ( line_counter = 0; line_counter < WORD_SIZE; line_counter++ )
        {
                for ( ab = 0; ab < 2; ab++ )
                {
                        mask = SIGN_BIT;
                        for ( i = 0; i < NIBBLES_IN_WORD; i++ )
                        {
                                for ( j = 0; j < NIBBLE_SIZE; j++ )
                                {
                                        printf ( "%c", ((( ab ) ? b : a ) &
mask ) ? '1' : '0' );
                                        mask >>= 1;
                                        }
                                printf ( " " );
                                }
                        printf ( "%s", ( ab ) ? "\n" : " " );
                        if ( ab )
                        {
                          b >>= 1;
                                }
                        else
                        {
                                a >>= 1;
#if defined(FIX_COMPILER_BUG)
# if (INTEGER == long)
                                a |= SIGN_BIT;    /* This is a work-around for
the 3b2 compiler bug. */
# endif
#endif
                                }
                        }
                }
        }

/* ----------------------------------------- */


  This little program might well produce some interesting surprises on
your machine in the same way it did on mine. I have an AT&T 3b2/400 and
use the K & R style compiler. Interestingly, the above program did what
I expected it to do when the integers were short, the sign bit is extended,
but when the integers are long the sign bit is NOT extended. In this case
the different behaviour is caused by the compiler always issuing a Logical
Shift instruction, when it should issue a Arithmetic Shift instruction for
signed integers and a Logical Shift instructon for unsigned ones. In the
case of the short int the varable is loaded from memory into the register
with a sign extend load instruction, this makes the Logical Shift instruction
right work correctly for short ints, but not for longs.  I had to examine
the assember codes output by the compiler in order to discover this.

  Here are the compiler invocation lines.

cc -olong.shifts -DFIX_COMPILER_BUG -DINTEGER=long shifts.c

        and

cc -oshort.shifts -DINTEGER=short shifts.c

        Experiment with the "-DFIX_COMPILER_BUG" and see what your compiler
does.


Lesson 5.


The Pre-processor and Header Files.


The pre-processor is activated by a '#' character in column one of the source
code. There are several statements vis:

#include

#define
#undef

#if
#else
#endif

#ifdef
#ifndef

#pragma

  #include
.

  In the programming examples presented in the previous lessons you will
probably have noticed that there is this statement:

#include <stdio.h>

right at the start of the program text. This statement tells the pre-processor
to include the named file in the your program text. As far as the compiler is
concerned this text appears just as if you had typed it yourself!

  This is one of the more useful facilities provided by the 'C' language.
The #include statement is frequently combined with the #if construct.
In this program fragment the file "true.h" is included in your program
if the pre-processor symbol FLAG is true, and "false.h" included if FLAG
is false.

#if ( FLAG )
# include "true.h"
#else
# include "false.h"
#endif


This mechanism has many uses, one of which is to provide
portability between all the 57,000 slightly different versions of unix and also
other operating systems. Another use is to be

Page : << Previous 10  Next >>