Reputation: 96
So I'm creating a Matrix structure however, when I try to populate the data, (see populateArray
in MatrixTest.c) all of my values are junk with the exception of the last value. Is there something wrong with how I allocated my memory or is it because of the scope of my variable (int data
) or is it something else?
Appreciate it!
MatrixImpl.c
#include <stdlib.h>
#include "Matrix.h"
void* getter( Matrix* matrix, int x, int y )
{
return getItem( matrix, x, y );
}
void setter( Matrix* matrix, int x, int y, void* const data, void (*userSetter)( Matrix*, int, int, void* const ) )
{
if( checkBounds( matrix, x, y ) )
{
userSetter( matrix, x, y, data );
}
}
void dtor( Matrix* matrix )
{
if( matrix->data )
{
free( matrix->data );
matrix->data = NULL;
}
}
void ctor( Matrix* matrix, void* const data )
{
matrix->data = data;
}
//returns true if in boundary of array
bool checkBounds( Matrix* matrix, int x, int y )
{
return ( matrix->stride.size2 > y && y >= 0 ) && ( matrix->stride.size1 > x && x >= 0 );
}
void* getItem( Matrix* matrix, int x , int y )
{
if( checkBounds( matrix, x, y ) )
{
return matrix->data + matrix->stride.size1 * y + x;
}
return NULL;
}
Matrix.h
#pragma once
#include <stdbool.h>
#define for_each( loopmaxX, loopmaxY, ... ) for( int y = 0; y < loopmaxY; y++ ){ for( int x = 0; x < loopmaxX; x++) { { __VA_ARGS__ } } }
typedef struct
{
void* data;
struct
{
int size1;
int size2;
} stride;
} Matrix;
void ctor( Matrix* , void* const );
void setter( Matrix*, int , int, void* const, void (*userSetter)(Matrix*, int, int, void* const));
void* getter( Matrix*, int, int );
void* getItem( Matrix*, int, int );
bool checkBounds( Matrix*, int, int );
void dtor( Matrix* );
MatrixTest.c
#include <stddef.h>
#include <assert.h>
#include <stdlib.h>
#include "Matrix.h"
void userSet( Matrix*, int, int, int* const );
void testIntAt( Matrix*, int, int , int );
void checkForNullData( Matrix* );
void checkBoundsForLoop( Matrix* );
void populateArray( Matrix* );
void checkMatrix( Matrix* );
int main()
{
Matrix matrix = { .data = NULL, .stride.size1 = 3, .stride.size2 = 3};
checkForNullData( &matrix );
int* chunck = (int*) malloc( sizeof( int ) * matrix.stride.size1 * matrix.stride.size2 );
ctor( &matrix, chunck );
populateArray( &matrix );
checkMatrix( &matrix );
dtor( &matrix );
}
void testIntAt( Matrix* matrix, int x, int y, int data )
{
assert( *(int*)getter( matrix, x, y ) == data );
}
void checkForNullData( Matrix* matrix )
{
assert( matrix->data == NULL );
}
void userSet( Matrix* matrix, int x, int y, int* const data )
{
*(int*)getter( matrix, x, y ) = *data;
printf( " %d\n", *(int*)getter( matrix, x, y ) );
}
void checkBoundsForLoop( Matrix* matrix )
{
for_each(
matrix->stride.size1, matrix->stride.size2,
assert( checkBounds( matrix, x, y ) );
);
}
void populateArray( Matrix* matrix )
{
for_each(
matrix->stride.size1, matrix->stride.size2,
int data = x + matrix->stride.size1 * y;
setter( matrix, x, y, &data, &userSet );
);
printf( "end populateArray\n" );
}
void checkMatrix( Matrix* matrix )
{
for_each(
matrix->stride.size1, matrix->stride.size2,
printf( " %d\n", *(int*)getter( matrix, x, y ) );
);
}
Example of output. Whats desired:
0
1
2
3
4
5
6
7
8
What I get:
50462976
67305985
84148994
100992003
117835012
134678021
526086
2055
8
Upvotes: 1
Views: 82
Reputation: 224082
In getItem
, this isn't doing what you expect:
return matrix->data + matrix->stride.size1 * y + x;
First pointer arithmetic on a void *
is not defined by the C standard although some compilers allow it as an extension, treating it the same way as a char *
. Assuming that's the case, this is incrementing the pointer not by the number of elements but by the number of bytes. You need to multiply that number by the element size.
So you need to add an extra field to Matrix
:
typedef struct
{
void* data;
struct
{
int size1;
int size2;
int esize;
} stride;
} Matrix;
Change the getter to use it:
void* getItem( Matrix* matrix, int x , int y )
{
if( checkBounds( matrix, x, y ) )
{
return (char *)matrix->data + (matrix->esize * (matrix->stride.size1 * y + x));
}
return NULL;
}
Change ctor
to set it:
void ctor( Matrix* matrix, void* const data, int esize )
{
matrix->data = data;
matrix->esize = esize;
}
And the call to ctor
:
ctor( &matrix, chunck, sizeof(int) );
Also, userSet
doesn't match the function pointer type setter
expects. Function pointers need to agree on the number and types of parameters and the return type. In this case the last argument has type int* const data
but the function pointer argument's last argument expects type void* const data
. So change the function last parameter type to match and change the body accordingly.
void userSet( Matrix* matrix, int x, int y, void* const data )
{
void *element = getter( matrix, x, y );
*(int*)element = *(int*)data;
printf( " %d\n", *(int*)element );
}
Upvotes: 5