GIDForums  

Go Back   GIDForums > Computer Programming Forums > C Programming Language
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 17-Jul-2008, 08:52
winner winner is offline
New Member
 
Join Date: Feb 2008
Posts: 18
winner is on a distinguished road

Giving garbage value as the result of product


I am new to pointers. I am trying to perform this multiplication, but this is giving garbage value. Can anyone please tell me my flaws. My code is posted below

CPP / C++ / C Code:
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
main(void)
{
	int n,c,s,a,b=2, m;
    double **dm,**dm1,**t;/*it will contain the  value at address of double variable*/
	puts("enter total no of rows");
	scanf("%d",&n);
	puts("enter total no of columns ");
	scanf("%d",&c);	
	
	/*My vector matrix*/
  printf("\n\nValues of Random Vector Matrix dm[][]n\n");
  dm = malloc(n * sizeof(double *));
  if (dm == NULL)
  {puts("Failure to allocate room for row pointers.");
    exit(0);
  }
    for (s = 0; s < n; s++)
    {dm[s] = malloc(c * sizeof(double));
     if (dm[s] == NULL)
	 {printf("Failure to allocate for s[%d]",s);
      exit(0);
     }
	}
    for(s=0;s<n;s++)
	{for(m=0;m<c;m++)
	{*(dm[s]+m)=((double)rand()/(double)RAND_MAX);
	printf("*(dm[%d]+%d)=%lf\t",s,m,*(dm[s]+m));}
		printf("\n");
	}

 

/*Transposition of vector matrix*/
  printf("\n\nTranspose of Original Vector Matrix dm1\n\n");
 dm1 = malloc(n * sizeof(double *));
  if (dm1 == NULL)
  {puts("Failure to allocate room for row pointers.");
    exit(0);
  }
    for (m = 0; m < c; m++)
    {dm1[m] = malloc(n * sizeof(double));
     if (dm1[m] == NULL)
	 {printf("Failure to allocate for m[%d]",m);
      exit(0);
     }
	}
  for(m=0; m<c; m++)
     {for(s=0; s<n; s++)
       { *(dm1[m]+s)=*(dm[s]+m);
	 printf("*(%lf\t",*(dm1[m]+s));
       }
      printf("\n");
     }

  /*product of transpose n vector matrix*/
 
printf("\n\nProduct of Transpose and Vector Matrix\n\n");
t = malloc(c * sizeof(double *));
if (t == NULL)
 {puts("Failure to allocate room for row pointers.");
  exit(0);
 }
for (a = 0; a < c; a++)
    {t[a] = malloc(c * sizeof(double));
     if (t[a] == NULL)
	 {
		 printf("Failure to allocate for a[%d]",a);
         exit(0);
     }
	}


	{for(a=0;a<c;a++)
      {for(b=0;b<c;b++)
	  {for(s=0;s<n;s++)
	      *(t[a]+b)+=(*(dm1[a]+s))*(*(dm[s]+b));/*This part of code not working*/
	   printf("%lf\t",*(t[a]+b));
	  }
       printf("\n");
      }
   }
	}

I am new to pointers, so please explain my fault if possible. Thanks in advance.
Last edited by admin : 17-Jul-2008 at 09:35. Reason: Please insert your example C/C++ codes between [CPP] and [/CPP] tags
  #2  
Old 17-Jul-2008, 11:06
ocicat ocicat is offline
Regular Member
 
Join Date: May 2008
Posts: 586
ocicat is a jewel in the roughocicat is a jewel in the rough

Re: Giving garbage value as the result of product


Quote:
Originally Posted by winner
I am new to pointers.
Yes, addressing can be contorted the first few times...

Several comments:
  • There are several ways in which memory can be allocated for an array. You have chosen a popular manner because it should make referencing any particular element simpler. It appears that you have done the allocation of a single array of double* representing the set of rows needed followed by each individual row of double correctly.
  • Where you are getting lost is in how to reference each individual element in assigning & accessing its value.
  • The formating gets weird too. I lost interest in dissecting the code after awhile.
  • You should also free up all heapspace at the end of execution.
The easiest way to keep the data structure straight in your mind is to recall that since each a[i] element is yet another row, it is also a double*. By adding the next dimension a[i][j], this adds the offset to each column element & dereferences it back to a double.

Consider the following simplified allocation of a two-dimensional array in two different ways:
CPP / C++ / C Code:
#include <stdio.h>
#include <stdlib.h>

#define ROWS            3
#define COLUMNS         4

int main()
{
    double *a, **b;
    int i, j, k = 0;

    a = (double*) malloc(ROWS * COLUMNS * sizeof(double));

    for (i = 0; i < ROWS; i++) 
        for (j = 0; j < COLUMNS; j++)
            a[i * ROWS + j] = k++ / 2.0;

    for (i = 0; i < ROWS; i++) {
        for (j = 0; j < COLUMNS; j++) 
            printf("%6.2f", a[i * ROWS + j]);
        printf("\n");
    }

    free(a);

    printf("\n");

    b = (double**) malloc(ROWS * sizeof(double*));
    for (i = 0; i < ROWS; i++)
        b[i] = (double*) malloc(COLUMNS * sizeof(double));

    for (i = 0; i < ROWS; i++) 
        for (j = 0; j < COLUMNS; j++)
            b[i][j] = k++ / 3.0;

    for (i = 0; i < ROWS; i++) {
        for (j = 0; j < COLUMNS; j++) 
            printf("%6.2f", b[i][j]);
        printf("\n");
    }

    for (i = 0; i < ROWS; i++)
        free(b[i]);
    free(b);

    return 0;
}
Freeing up all heapspace allocations at the end is not merely a pedantic exercise, it is a responsible practice. I have sent large corporate databases in development crash after several days of execution due to memory leaks. Debugging that mess took an entire staff months, & given the cost of paying that staff, several millions of dollars were spent chasing down where memory was not being freed properly.

Lastly, don't underestimate the value of formating. It can help you keep life straight, & given that most programming in the corporate world is collaborative, it makes life easier for the next person who has to figure out what you meant.
  #3  
Old 17-Jul-2008, 14:02
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 5,311
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: Giving garbage value as the result of product


Quote:
Originally Posted by winner
I am new to pointers....

First of all, you simply must get familiar with the feature of the language that connects pointer notation with array notation.

One fundamental and unbelievably important notational definition is the following:

If a is a pointer data type and if b is a integer data type then the notation
Code:
*(a+b)
is exactly the same as

Code:
a[b]

Not "nearly the same as" or "just about the same as," but exactly the same as.

You can use the two notations interchangeably. Note that this is not (that's not) saying that pointers are the same as arrays; this is just notation.


Suppose that the variable x is a "pointer to pointer" data type. Then *x is a pointer data type.

Suppose y is an integer data type, then, from the previous definition, the notation
Code:
*(x + y)
is the same as
Code:
x[y]

Note that: if x is a pointer-to-pointer, then *x is a pointer.

Then an application of the array-pointer notational equivalence says that if i and j are integer data types and x is a pointer-to-pointer data type, the notation
Code:
*(x[i]+j)
is exactly the same as
Code:
x[i][j]
Again, I emphasize that we are not saying that pointers are the same as arrays; it's just notation.

Now, for people familiar with matrix notation from math class, I think they are more likely to appreciate matrix notation in C, although pointer notation and mixed array-pointer notation that you used is perfectly valid.

Your program declares pointers-to-pointers and allocates storage so that they can be used to store matrix elements. I would use matrix notation for the manipulations. Try writing your transpose loop with something like
CPP / C++ / C Code:
    dm1[m][s] = dm[s][m];
Instead of
CPP / C++ / C Code:
    *(dm1[m]+s)=*(dm[s]+m);
Which is easier to visualize? I can tell "at a glance" what the first statement is doing, but the second takes some little thought.

Now, try it with the product calculation.

Here's the general approach. You customize it for your application:

Suppose you have an m x q matrix, x and a q x n matrix y

Then the product is an m x n matrix.

Now, let's illustrate using matrix notation in a loop to do matrix multiplication in C. Suppose we want to multiply matrix x by matrix y. I'll call x the "left matrix" and y will be the "right matrix." The product will be named z

I use the following variables:

1. Let lrows be the number of rows if the left matrix.

2. Let lcols be the number of columns in the left matrix. This must be equal to rows in the right matrix, otherwise the matrix product is not defined.

3. Let rcols be the number of columns in the right matrix.

(I like to let the variable names be somewhat descriptive rather than using names like m, n, etc., so that I won't forget what each actually means.) Also, when making loops over rows and columns, I usually use i and j, since in math class, they typically talk about M(i,j) for the matrix element on the ith row and the jth column.

Suppose you have already declared variables and allocated storage as required.

Then, here's the code to multiply the matrices:

CPP / C++ / C Code:
        int i;
        int j;
        int k;
.
.
.
        for (i = 0; i < lrows; i++) {
            for (j = 0; j < rcols; j++) {
                z[i][j] = 0;
                for (k = 0; k < lcols; k++) {
                    z[i][j] += x[i][k]*y[k][j];
                }
            }
        }

Regards,

Dave

Footnote: I hate to repeat myself, but I am not saying that matrices and pointers are interchangeablle. They are not. Never have been; never will be. The notation, however is interchangeable. Absolutely. Completely. Unequivocally.

The notation x[i][j] can be used to access an element of a declared array or an element of a dynamically allocated array (using pointers-to-pointers). The code created by the compiler to access the elements of each kind of "array" is completely different for the two cases. If you write a function that works with "pointer-to-pointer" arguments, you must feed it an argument that is a "pointer-to-pointer," not the name of an array. If you write a function that takes the name of 2-D array as an argument, you can't feed it a "pointer-to-pointer." Notation inside either function can use pointer notation or array notation or mixed notation. The source code can look the same, but the code generated by the compiler is different.
  #4  
Old 17-Jul-2008, 14:56
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 5,311
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: Giving garbage value as the result of product


Quote:
Originally Posted by ocicat
Consider the following...
CPP / C++ / C Code:
.
.
.
#define ROWS            3
#define COLUMNS         4
.
.
.
    for (i = 0; i < ROWS; i++) 
        for (j = 0; j < COLUMNS; j++)
            a[i * ROWS + j] = k++ / 2.0;
.
.
.

It's gotta be
CPP / C++ / C Code:
            a[i * COLUMNS + j] = ...whatever...
You can see that there is a problem if you actually print the result of your first example;

Code:
0.00 0.50 1.00 2.00 2.00 2.50 3.00 4.00 4.00 4.50 5.00 5.50
What happened to 2.50? What happened to 3.50?

Try the following as your first loop:
CPP / C++ / C Code:
    for (i = 0; i < ROWS; i++) {
        for (j = 0; j < COLUMNS; j++) {
            printf("Index = %d\n", i*ROWS+j);
            a[i * ROWS + j] = k++ / 2.0;
        }
    }


Output:
Code:
Index = 0 Index = 1 Index = 2 Index = 3 Index = 3 Index = 4 Index = 5 Index = 6 Index = 6 Index = 7 Index = 8 Index = 9 0.00 0.50 1.00 2.00 2.00 2.50 3.00 4.00 4.00 4.50 5.00 5.50

(Now change "ROWS" to "COLUMNS" in the index calculation expression and try it.)



With i = 0 (the first conceptual "row") the first elements go from a[0] through a[COLUMNS-1]

Then, with i = 1 (the next conceptual "row") the elements go from a[COLUMNS] through a[2*COLUMNS=1]

Etc.

So, we can see that the (i,j) element would be addressed by a[i*COLUMNS + j]

Of course, this is how C lays out a 2-D declared array in consecutive memory locations, and is useful in some applications using a pointer to an allocated block.

There may be some advantages, in certain applications, to the single-block method of your first example, but the disadvantage is that it's not always obvious when even experienced programmers absent-mindedly get it wrong. It's that kind of bug that isn't always obvious "at a glance."

This points out the advantage of letting the compiler do the work by using 2-D array notation for "pointer-to-pointer" dynamically allocated arrays as you show in your second example. The Original Poster did the work of allocating the 2-D arrays but didn't glom onto the convenience of the 2-D array notation that you showed.


Regards,

Dave

Footnote: The fact that the C compiler calculates the address of the (i,j) element of a 2-D declared array by the formula i*COLUMNS+j means that for functions with parameters that are declared arrays, you have to tell it the size of the second dimension but not the first when you define the function. In C, the compiler has to know how to access the elements at compile time, not run time.
  #5  
Old 17-Jul-2008, 18:49
ocicat ocicat is offline
Regular Member
 
Join Date: May 2008
Posts: 586
ocicat is a jewel in the roughocicat is a jewel in the rough

Re: Giving garbage value as the result of product


Quote:
Originally Posted by davekw7x
It's gotta be
CPP / C++ / C Code:
            a[i * COLUMNS + j] = ...whatever...
Thanks for catching my error. Now I know as least one person read it!

The point is that the heapspace is being utilized row-major.

Quote:
There may be some advantages, in certain applications, to the single-block method of your first example, but...
Yes, the point was to show that there is more than one alternative. Allocating a single block of memory is:
  • simpler to terms of the allocation, but the burden of indexing is thrusted upon the programmer.
  • takes less memory. The second example requires an array of addresses which are used only as indexes into subsequent heapspace allocations. The point is that if the beginning of any row cannot be computed (illustrated by the first example), it has to be stored (illustrated by the second example). Memory conservation may be an issue in embedded environments where the amount of memory available is small.
Quote:
The fact that the C compiler calculates the address of the (i,j) element of a 2-D declared array by the formula i*COLUMNS+j means that for functions with parameters that are declared arrays, you have to tell it the size of the second dimension but not the first when you define the function.
You can generalize this statement further. Because instructions for indexing are being generated by the compiler, multidimensional arrays require all rightmost dimensions to be known. Only the leftmost dimension can remain unspecified. In the case of three dimensions:
CPP / C++ / C Code:
#include <stdio.h>

#define D1      2
#define D2      3
#define D3      4

void output(int[][D2][D3]);

int main()
{
    int i, j, k, a[D1][D2][D3];

    for (i = 0; i < D1; i++)
        for (j = 0; j < D2; j++)
            for (k = 0; k < D3; k++)
                a[i][j][k] = i + j + k;

    output(a);

    return 0;
}

void output(int a[][D2][D3])
{
    int i, j, k;

    for (i = 0; i < D1; i++) {
        for (j = 0; j < D2; j++) {
            for (k = 0; k < D3; k++)
                printf("%4d", a[i][j][k]);
            printf("\n");
        }
        printf("\n");
    }
}
  #6  
Old 18-Jul-2008, 00:22
winner winner is offline
New Member
 
Join Date: Feb 2008
Posts: 18
winner is on a distinguished road

Re: Giving garbage value as the result of product


Quote:
Originally Posted by davekw7x
Notation inside either function can use pointer notation or array notation or mixed notation. The source code can look the same, but the code generated by the compiler is different.

I am declaring the variable as pointer to pointer but using it in form of mixed array pointer notation. Will the compiler then behave differently?
  #7  
Old 18-Jul-2008, 00:30
winner winner is offline
New Member
 
Join Date: Feb 2008
Posts: 18
winner is on a distinguished road

Re: Giving garbage value as the result of product


@ Ocicat

You said to free the allocation of heap.

There comes question in my mind,that..

Suppose in case of my program,i Would want to free the space used by **dm and **dm1,then should i do it after the multiplication is over???Otherwise,before execution I will lose the address location.


One more question,Does use of macros in case of large programs(say variable numbering 1000) makes the program slow???If it does what is the other way to input the variable dyanamically.I dont want a static allocation.Is user input the second option?
Thanks in advance


Winner
  #8  
Old 18-Jul-2008, 00:57
ocicat ocicat is offline
Regular Member
 
Join Date: May 2008
Posts: 586
ocicat is a jewel in the roughocicat is a jewel in the rough

Re: Giving garbage value as the result of product


Quote:
Originally Posted by winner
...should i do it after the multiplication is over???
Yes.
Quote:
Does use of macros in case of large programs(say variable numbering 1000) makes the program slow???
I assume you are referring to the dimensions of the matrix.

On the platform I am using, sizeof(double) shows that a double consumes 8 bytes. Therefore, a 1000 * 1000 matrix means there are 1,000,000 matrix elements allocated from the heap. At 8 bytes per element, you are asking the program to allocate 8 * 1,000,000 / (1024 * 1024) = greater than 7.5 MB just for this matrix alone. Not knowing either what operating system you are using, how much RAM your system has installed, or what other applications are running at the moment, as you push the size of the matrix to extremes the operating system will have to begin paging memory contents to disk at some point. Yes, you will see performance degrade by allocating significant quantities of memory.
  #9  
Old 18-Jul-2008, 07:32
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 5,311
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: Giving garbage value as the result of product


Quote:
Originally Posted by winner
I am declaring the variable as pointer to pointer but using it in form of mixed array pointer notation. Will the compiler then behave differently?
My example showed how to use array notation with a variable like yours that was declared a pointer-to-pointer (and it allocated memory for the "array" as you did). The example loops also showed how to calculate the product of two matrices. Did you try it?

Here's the deal:
You write the code. The compiler does whatever it has to in order to access the memory.

Regards,

Dave

Footnote: The source code in the loops in my example would look the same if any (or all) of the variables x, y, and z had been declared as a 2-D array, but the compiler would treat it differently. The source code notation for accessing elements of declared arrays is the same as the source code notation for dynamically allocated "arrays." The compiler knows what to do. You simply have to believe in the equivalence of the notations that I showed.
Last edited by davekw7x : 18-Jul-2008 at 08:59.
  #10  
Old 18-Jul-2008, 10:33
ocicat ocicat is offline
Regular Member
 
Join Date: May 2008
Posts: 586
ocicat is a jewel in the roughocicat is a jewel in the rough

Re: Giving garbage value as the result of product


Quote:
Originally Posted by winner
I am declaring the variable as pointer to pointer but using it in form of mixed array pointer notation. Will the compiler then behave differently?
Let's revisit this question.

Your code essentially does the following:
CPP / C++ / C Code:
double **dm = malloc(n * sizeof(double *));
...which instructs the compiler to treat the address assigned to dm as two indirections to a double.

Later in your code, you specify in effect:
CPP / C++ / C Code:
dm[i][j] = 1.0;
What this means is:
  1. Since dm itself was originally defined as two indirections away from a double value, dm[i] dereferences back to just a single indirection. Given that dm was defined as a "pointer-to-a-pointer", the expression dm[i] simply represents an address to a double. The expression dm[i] is also identical to *(dm + i) & the instructions generated at the assembly language level will be identical for both expressions.
  2. If dm[i] is the address of a double, adding the second subscript as in dm[i][j] dereferences dm[i] to point to the jth element offset from dm[i]. Notation-wise:
    CPP / C++ / C Code:
    dm[i][j] == (dm[i])[j] == (*(dm + i))[j] == *(*(dm + i) + j)
    In other words, if dm[i][j] is meant to represent a double value, dm has to be defined as a double**.
  3. Given that the expression dm[i][j] dereferences dm back to a double,
    CPP / C++ / C Code:
    dm[i][j] = 1.0;
    ...the assignment should appear trivial. 1.0 is to be written to the memory location specified by the expression dm[i][j].
The preciseness of the syntax instructs the compiler exactly what assembly language instructions to generate. There is no guess work involved.
Last edited by ocicat : 18-Jul-2008 at 11:53.
 
 

Recent GIDBlogInstall Adobe Flash - Without Administrator Rights by LocalTech

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
How to choose an ecommerce product? ramukumar eCommerce / Merchant Account Forum 1 12-Jun-2008 07:14
Memory de-allocation during debugging gaoanyu C Programming Language 12 19-Dec-2005 04:50
Hex Result giving strange answers. Rosdahale C Programming Language 6 07-Dec-2004 20:28
fltk-2.0 cvs Plumb FLTK Forum 20 13-Nov-2004 07:10
[Review] SalesCart Pro BobbyDouglas Web Design Forum 0 11-Mar-2004 12:09

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 12:33.


vBulletin, Copyright © 2000 - 2010, Jelsoft Enterprises Ltd.