In response to a thread on the TRS-80 Color Computer FB group, I wrote a little program to demonstrate a few of the problems you run into when treating pointers to one integer type as pointers to another.
- /* A little program to demonstrate a few of the dangers
- ** of aliasing pointers to different types of integers.
- **
- ** To fully appreciate the effects,
- ** compile and run this code on both LSB1st and MSB1st CPUs.
- **
- ** Written in response to a thread on the TRS-80 Color Computer FB group.
- **
- ** Joel Rees, Amagasaki, Japan, November 2020.
- */
- #include <stdlib.h>
- #include <limits.h>
- #include <stdio.h>
- typedef char * byteptr_t;
- typedef short * shortptr_t;
- typedef long * longptr_t;
- int main( int argc, char *argv[] )
- {
- short int shorttest[ 3 ] = { 0, 0, 0 };
- long int longtest[ 3 ] = { 0, 0, 0 };
- shortptr_t shortptr;
- longptr_t longptr;
- printf( "Note that both\n"
- "least significant first and most significant first\n"
- "give unfortanate results.\n"
- "Different, but both unfortunate.\n"
- "Now that you know they do, see if you can figure out why.\n\n" );
- printf( "Let's start with referring to a long as a short, all target bits clear.\n\n" );
- shortptr = (short *) &longtest[ 1 ];
- printf( "longtest before: %ld %ld %ld (hex: %lx %lx %lx)\n",
- longtest[ 0 ], longtest[ 1 ], longtest[ 2 ], longtest[ 0 ], longtest[ 1 ], longtest[ 2 ] );
- printf( "Test: ( * shortptr ) = 1 \n" );
- ( * shortptr ) = 1;
- printf( "longtest after: %ld %ld %ld (hex: %lx %lx %lx)\n",
- longtest[ 0 ], longtest[ 1 ], longtest[ 2 ], longtest[ 0 ], longtest[ 1 ], longtest[ 2 ] );
- printf( "We thought we wrote: %d. We actually wrote %ld between %ld and %ld.\n",
- * shortptr, longtest[ 1 ], longtest[ 0 ], longtest[ 2 ] );
- printf( "In hexadecimal,\n" );
- printf( "We thought we wrote: %x. We actually wrote %lx between %lx and %lx.\n",
- * shortptr, longtest[ 1 ], longtest[ 0 ], longtest[ 2 ] );
- printf( "\nAgain, setting all target bits,\n" );
- longtest[ 0 ] = longtest[ 1 ] = longtest[ 2 ] = -1;
- printf( "longtest before: %ld %ld %ld (hex: %lx %lx %lx)\n",
- longtest[ 0 ], longtest[ 1 ], longtest[ 2 ], longtest[ 0 ], longtest[ 1 ], longtest[ 2 ] );
- printf( "Test: ( * shortptr ) = 1 \n" );
- ( * shortptr ) = 1;
- printf( "longtest after: %ld %ld %ld (hex: %lx %lx %lx)\n",
- longtest[ 0 ], longtest[ 1 ], longtest[ 2 ], longtest[ 0 ], longtest[ 1 ], longtest[ 2 ] );
- printf( "We thought we wrote: %d. We actually wrote %ld between %ld and %ld.\n",
- * shortptr, longtest[ 1 ], longtest[ 0 ], longtest[ 2 ] );
- printf( "In hexadecimal,\n" );
- printf( "We thought we wrote: %x. We actually wrote %lx between %lx and %lx.\n",
- * shortptr, longtest[ 1 ], longtest[ 0 ], longtest[ 2 ] );
- printf( "\n\nClearing all target bits,\n" );
- longtest[ 0 ] = longtest[ 1 ] = longtest[ 2 ] = 0;
- printf( "longtest before: %ld %ld %ld (hex: %lx %lx %lx)\n",
- longtest[ 0 ], longtest[ 1 ], longtest[ 2 ], longtest[ 0 ], longtest[ 1 ], longtest[ 2 ] );
- printf( "Test: ( * shortptr ) = -1 \n" );
- ( * shortptr ) = -1;
- printf( "longtest after: %ld %ld %ld (hex: %lx %lx %lx)\n",
- longtest[ 0 ], longtest[ 1 ], longtest[ 2 ], longtest[ 0 ], longtest[ 1 ], longtest[ 2 ] );
- printf( "We thought we wrote: %d. We actually wrote %ld between %ld and %ld.\n",
- * shortptr, longtest[ 1 ], longtest[ 0 ], longtest[ 2 ] );
- printf( "In hexadecimal,\n" );
- printf( "We thought we wrote: %x. We actually wrote %lx between %lx and %lx.\n",
- * shortptr, longtest[ 1 ], longtest[ 0 ], longtest[ 2 ] );
- printf( "\nAgain, setting all target bits,\n" );
- longtest[ 0 ] = longtest[ 1 ] = longtest[ 2 ] = -1;
- printf( "longtest before: %ld %ld %ld (hex: %lx %lx %lx)\n",
- longtest[ 0 ], longtest[ 1 ], longtest[ 2 ], longtest[ 0 ], longtest[ 1 ], longtest[ 2 ] );
- printf( "Test: ( * shortptr ) = -1 \n" );
- ( * shortptr ) = -1;
- printf( "longtest after: %ld %ld %ld (hex: %lx %lx %lx)\n",
- longtest[ 0 ], longtest[ 1 ], longtest[ 2 ], longtest[ 0 ], longtest[ 1 ], longtest[ 2 ] );
- printf( "We thought we wrote: %d. We actually wrote %ld between %ld and %ld.\n",
- * shortptr, longtest[ 1 ], longtest[ 0 ], longtest[ 2 ] );
- printf( "In hexadecimal,\n" );
- printf( "We thought we wrote: %x. We actually wrote %lx between %lx and %lx.\n",
- * shortptr, longtest[ 1 ], longtest[ 0 ], longtest[ 2 ] );
- printf( "\n\nTime for arithmetic on small integers.\n" );
- printf( "Clearing ..." );
- longtest[ 0 ] = longtest[ 1 ] = longtest[ 2 ] = 0;
- printf( "longtest before: %ld %ld %ld (hex: %lx %lx %lx)\n",
- longtest[ 0 ], longtest[ 1 ], longtest[ 2 ], longtest[ 0 ], longtest[ 1 ], longtest[ 2 ] );
- printf( "Test: ( * shortptr ) -= 1 (subtract 1)\n" );
- ( * shortptr ) -= 1;
- printf( "* shortptr sees %d (%x)\n", * shortptr, *shortptr );
- printf( "longtest after: %ld %ld %ld (hex: %lx %lx %lx)\n",
- longtest[ 0 ], longtest[ 1 ], longtest[ 2 ], longtest[ 0 ], longtest[ 1 ], longtest[ 2 ] );
- printf( "\nClearing ..." );
- longtest[ 0 ] = longtest[ 1 ] = longtest[ 2 ] = 0;
- printf( "longtest before: %ld %ld %ld (hex: %lx %lx %lx)\n",
- longtest[ 0 ], longtest[ 1 ], longtest[ 2 ], longtest[ 0 ], longtest[ 1 ], longtest[ 2 ] );
- printf( "Test: ( * shortptr ) += 1 (add 1)\n" );
- ( * shortptr ) += 1;
- printf( "* shortptr sees %d (%x)\n", * shortptr, *shortptr );
- printf( "longtest after: %ld %ld %ld (hex: %lx %lx %lx)\n",
- longtest[ 0 ], longtest[ 1 ], longtest[ 2 ], longtest[ 0 ], longtest[ 1 ], longtest[ 2 ] );
- /********/
- printf( "\n\n\nNow let's refer to a short as a long.\n\n" );
- longptr = (long *) &shorttest[ 1 ];
- printf( "shorttest before: %d %d %d (hex: %x %x %x)\n",
- shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ], shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ] );
- printf( "Test: ( * longptr ) = 1 \n" );
- ( * longptr ) = 1;
- printf( "shorttest after: %d %d %d (hex: %x %x %x)\n",
- shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ], shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ] );
- printf( "We thought we wrote: %ld. We actually wrote %d between %d and %d.\n",
- * longptr, shorttest[ 1 ], shorttest[ 0 ], shorttest[ 2 ] );
- printf( "In hexadecimal,\n" );
- printf( "We thought we wrote: %lx. We actually wrote %x between %x and %x.\n",
- * longptr, shorttest[ 1 ], shorttest[ 0 ], shorttest[ 2 ] );
- printf( "\nAgain, setting all target bits,\n" );
- shorttest[ 0 ] = shorttest[ 1 ] = shorttest[ 2 ] = -1;
- printf( "shorttest before: %d %d %d (hex: %x %x %x)\n",
- shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ], shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ] );
- printf( "Test: ( * longptr ) = 1 \n" );
- ( * longptr ) = 1;
- printf( "shorttest after: %d %d %d (hex: %x %x %x)\n",
- shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ], shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ] );
- printf( "We thought we wrote: %ld. We actually wrote %d between %d and %d.\n",
- * longptr, shorttest[ 1 ], shorttest[ 0 ], shorttest[ 2 ] );
- printf( "In hexadecimal,\n" );
- printf( "We thought we wrote: %lx. We actually wrote %x between %x and %x.\n",
- * longptr, shorttest[ 1 ], shorttest[ 0 ], shorttest[ 2 ] );
- printf( "\n\nClearing all target bits,\n" );
- shorttest[ 0 ] = shorttest[ 1 ] = shorttest[ 2 ] = 0;
- printf( "shorttest before: %d %d %d (hex: %x %x %x)\n",
- shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ], shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ] );
- printf( "Test: ( * longptr ) = -1 \n" );
- ( * longptr ) = -1;
- printf( "shorttest after: %d %d %d (hex: %x %x %x)\n",
- shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ], shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ] );
- printf( "We thought we wrote: %ld. We actually wrote %d between %d and %d.\n",
- * longptr, shorttest[ 1 ], shorttest[ 0 ], shorttest[ 2 ] );
- printf( "In hexadecimal,\n" );
- printf( "We thought we wrote: %lx. We actually wrote %x between %x and %x.\n",
- * longptr, shorttest[ 1 ], shorttest[ 0 ], shorttest[ 2 ] );
- printf( "\nAgain, setting all target bits,\n" );
- shorttest[ 0 ] = shorttest[ 1 ] = shorttest[ 2 ] = -1;
- printf( "shorttest before: %d %d %d (hex: %x %x %x)\n",
- shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ], shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ] );
- printf( "Test: ( * longptr ) = -1 \n" );
- ( * longptr ) = -1;
- printf( "shorttest after: %d %d %d (hex: %x %x %x)\n",
- shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ], shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ] );
- printf( "We thought we wrote: %ld. We actually wrote %d between %d and %d.\n",
- * longptr, shorttest[ 1 ], shorttest[ 0 ], shorttest[ 2 ] );
- printf( "In hexadecimal,\n" );
- printf( "We thought we wrote: %lx. We actually wrote %x between %x and %x.\n",
- * longptr, shorttest[ 1 ], shorttest[ 0 ], shorttest[ 2 ] );
- printf( "\n\nTime for arithmetic on small integers.\n" );
- printf( "Clearing ..." );
- shorttest[ 0 ] = shorttest[ 1 ] = shorttest[ 2 ] = 0;
- printf( "shorttest before: %d %d %d (hex: %x %x %x)\n",
- shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ], shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ] );
- printf( "Test: ( * longptr ) -= 1 (subtract 1)\n" );
- ( * longptr ) -= 1;
- printf( "* longptr sees %d (%x)\n", * shortptr, *shortptr );
- printf( "shorttest after: %d %d %d (hex: %x %x %x)\n",
- shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ], shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ] );
- printf( "\nClearing ..." );
- shorttest[ 0 ] = shorttest[ 1 ] = shorttest[ 2 ] = 0;
- printf( "shorttest before: %d %d %d (hex: %x %x %x)\n",
- shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ], shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ] );
- printf( "Test: ( * longptr ) += 1 (add 1)\n" );
- ( * longptr ) += 1;
- printf( "* longptr sees %d (%x)\n", * shortptr, *shortptr );
- printf( "shorttest after: %d %d %d (hex: %x %x %x)\n",
- shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ], shorttest[ 0 ], shorttest[ 1 ], shorttest[ 2 ] );
- printf( "To get the full effect of this,\n"
- "be sure to compile and run on both least significant first\n"
- "and most significant first architectures.\n"
- "Ask yourself, \n"
- "on which architecture will you notice the effects more quickly?\n\n" );
- return EXIT_SUCCESS;
- }