From: ktf@bc3.GUN.de (Klaus ter Fehn)
Subject: Re: The 2-Dee Array Deelemna
Organization: private
Date: Thu, 7 Jan 1993 17:30:11 GMT



In comp.lang.c you write:

>In addition, I would greatly appreciate it if someone
>could explain (with crude ASCII drawings) *, **, and &.
>I find it easiest to learn with drawings when it comes
>to pointers (its how I learned PASCAL), but C is a 
>new cup of tea, and a picture is worth a thousand words <: 

>more malloctest.c
>#include <stdio.h>

>main ()
>{

>int i,j;

>int nrows, ncolumns;
>int **array;               /* 1) corrected, moved from 2) below */

>ncolumns = 10;

>printf ("Enter array index: \n");
>scanf ("%d", &nrows);


>array = (int **) malloc (nrows * sizeof(int *)); /* 2) int declaration moved to 1) */
>for (i=0; i < nrows; i++)
>  array[i] = (int *) malloc (ncolumns * sizeof(int));  /* removed * before last int */

>printf ("Reading array values, and printing\n");

Your first index [i] is counting rows and the second [j] the columns
so change the loop:

> /* for (i=0; i<10; i++) */      for (i = 0; i < nrows; i++)
> /*  for (j=0; j<nrows; j++) */   for (j = 0; j < ncolumns; j++)
>  {
>    printf("%d x %d = %d\n",i,j,i*j);
>    array[i][j] = i*j;   /* dbx reports this as the location of the bus error */
>    printf("%d,%d = %d\n",i,j,array[i][j]);

>  }

>}

>Ok, basically, this is the program.  I moved int **array up with the other declarations,
>as you all told me to do, and removed a * before the last int (I would greatly
>appreciate a good explanation of why this is so).

(...)

>Now I am looking for

>1) The reason I am getting this annoying bus error.
>2) An explanation, with crude ASCII pictures, of *, **, and & in C.
>3) An explanation of why | array[i] = (int *) malloc (ncolumns * sizeof(int));
>   I was told to remove the star here ----------------------------------^ before int.

1) See the changes I made in your code above (the for-loops)
   You mixed up i and j / rows and columns and perhaps writing to an
   memory location, you were not allowed to access.

2) I take your example:

I assume nrows is 2 and ncolumns is 3 (otherwise it'll be too much to draw
within vi :-)

int **array	
  ,---.
  | o |    A pointer to a location, where a integer-pointer resides
  `-+-' 
     \
      _|
	,---.      Two pointers to location, where integer-values reside.
    [0] | o-+      The two integer-pointers, you malloc()ed space for in your
	+---+ \    first malloc():
    [1] | o |  |   array = (int **) malloc (nrows * sizeof(int *));
	`-+-'  |  
          |     \ 
          |      _| [0][0] [0][1] [0][2]
	  |        ,------+------+------.  The two areas to store the integer-
	  | 	   |      |      |      |  values, you malloc()ed with your
	  | 	   `------+------+------'  second malloc() (in the loop)
         \|/
	 ,------+------+------.
	 |      |      |      |
	 `------+------+------'
	  [1][0] [1][1] [1][2]

An other example to show the meanings of **, * and &:

	int value, *pointer, **doublepointer;

	value = 777;
	pointer = &value;
	doublepointer = &pointer;

Let us assume, that the vars lie on the following locations:

	varname    memory location  stored value
	value		1000		777
	pointer		1004		1000
	doublepointer	1008		1004

Then the following expressions have the shown results:

expression	result	meaning
&value		1000	adress of 'value'
value		777     value of 'value'
&pointer	1004    adress of 'pointer'
pointer		1000	value of 'pointer'
*pointer	777	value of adress where 'pointer' points to
&doublepointer	1008    adress of 'doublepointer'
doublepointer	1004	value of 'doublepointer'
*doublepointer	1000    value of adress where 'doublepointer' points to
**doublepointer	777     value of adress where the value of the memory 
			location where 'doublepointer' points to, points to
			(uhrg)



>3) An explanation of why | array[i] = (int *) malloc (ncolumns * sizeof(int));
>   I was told to remove the star here ----------------------------------^ 
>   before int.

Well - it would make no sense: you want to allocate ncolumns integer-values,
so you got to allocate (ncolumns * sizeof(int)) bytes.

Also it will make no sense for the compiler. What is a (* int) ?!? If you
intended to say 'integer-pointer' it would be (int *).

Greetings from Germany...
-- 
Klaus ter Fehn		<ktf@bc3.GUN.de>
Neanderstr. 4		{mcshh,smurf,unido}!easix!bc3!ktf
4000 Duesseldorf 1
FRG / Germany		Tel.: +49-211-676331