0

I have code which already works but am trying to extend it.

unsigned char **data_ptr;

Allocate memory for the first "array"

data_ptr = (unsigned char **)malloc(sizeof(unsigned char **) * no_of_rows);

Then in a loop initialize each row

data_ptr[index] = (unsigned char *)malloc(sizeof(unsigned char*), rowsize));

I then pass the address of my array to a library function. It works fine if I just pass the start of a row...

LibFunction( info_ptr,  &data_ptr[index] )  //OK

But I need to pass the address of where in a row I want the function to begin writing data. These both compile but fail in operation

LibFunction( info_ptr,(unsigned char **)data_ptr[index] + 1); 

or..

LibFunction( info_ptr,(unsigned char **)data_ptr[index][1]);

LibFunction is of the form

LibFunction(..., unsigned char **)

I'm allocating more memory than I need with rowsize so I don't think I'm overrunning the array. As I stated, the code works fine if I pass it the start of a row but bugs out if I try to pass any other element. There may be something else wrong but I need to know first if my syntax is ok.

Can't find anything else on the net as regards passing the address of single element of dynamic 2d array.

1
  • 2
    Are all rows are equal in size? If so, do yourself a favor and allocate one big array for all of them. Commented Jan 25, 2013 at 13:33

6 Answers 6

1
LibFunction( info_ptr,(unsigned char **)data_ptr[index] + 1);

is wrong because data_ptr is an unsigned char **, so data_ptr[index] is an unsigned char *. Leave out the cast and correct the function you're calling, it should accept an unsigned char *.

Sign up to request clarification or add additional context in comments.

1 Comment

The horrible casting was an attempt to correct compile errors. But your comment regarding correcting the function hit the nail on the head and let me see what the real problem was. I couldn't change the function (third party library) but I did manage to locate another function in the header files which did the same job but accepted a variable with one less level of indirection. Thanks!
1

Some corrections in your program, observed from the top few lines

Since,

unsigned char **data_ptr; // a pointer to a char pointer

get the sizeof(char*) and always avoid typecasting the pointer returned by malloc()

data_ptr = malloc(sizeof(unsigned char *) * no_of_rows);

And for doing the allocation for the rows,

data_ptr[index] = (unsigned char *)malloc(sizeof(unsigned char*)* rowsize));

To pass the address of where in a row you want the function to begin writing data, change the function signature as

LibFunction(..., unsigned char *)

2 Comments

How do I avoid typecasting the pointer returned by malloc? I now have my code working but still have to rely on the casts.
If you are using C and If your lvalue is of right type, you need not do typecasting. we have the implicit type cast behaviour of void* returned by malloc.
0

It should be LibFunction(&data_ptr[row][start_here]), exactly the same as if it was just an unsigned char[ROWS][COLUMNS];.

In general, it is my experience that if you think you require casts in modern-day C, it is probable that you are muddled up with what you are trying to do. A nice read is a comment on a post by Linus Torvalds on /. on this kind of stuff.

1 Comment

I should have mentioned that I'm compiling as C++. The casts are in response to compile errors. And you're right, I will read that Torvald document.
0

You're not allocating room for no_of_rows pointers to pointers; there's an asterisk too many in there. Also, you really [shouldn't cast the return value of malloc(), in C][1].

Your first allocation should be:

data_ptr = malloc(no_of_rows * sizeof *data_ptr);

Comments

0

But I need to pass the address of where in a row I want the function to begin writing data

So let's start simple, to make an array the correct size, forget trying to get the sizeof a complex type, we can simply do this:

unsigned char **data_ptr;
data_ptr = malloc(sizeof(data_ptr) * no_of_rows); //Just sizeof your var

Now you've got the correct memory malloc'd next you can malloc the memory for the rest easily:

for(index = 0; index < no_of_rows; index++)
  data_ptr[index] = malloc(sizeof(unsigned char*) * rowsize);

Last point, now that we've got all that set up, you should initialize your array:

for(index = 0; index < no_of_rows; index++)
  for(index2 = 0; index2 < rowsize; index2++)
     data_ptr[index][index2] = 0;

As for your function, you want it to take a "portion" of an array, so we need it to take an array and a size (the length of the array to initialize):

void LibFunction(unsigned char data[], int size);

Then we're your ready to store some data it's as easy as:

LibFunction(&data_ptr[1][2], 3);  // store data in second row, 3rd column, store
                                  // three values.

1 Comment

As stated in comment above, I'm dealing with a third party library so can't change the function, at least not without a recompile and explaining to my boss why I need to recompile a networked library!!
0

You can do something like this:

unsigned char* ptr = &data[0][1];
LibFunction(info_ptr, &ptr);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.