I have code like this:
#include <stdio.h>
#include <stdlib.h>
int main() {
int x=10;
int y=10;
int **data = (int**) malloc(x * sizeof(int));
if(!**data){
printf("Error");
return 1;
}
for(int i=0;i<x;i++){
*(data+i) = (int*) malloc(y * sizeof(int));
if(!*(data+i)){
printf("Error");
return 1;
}
}
for(int i=0;i<x;i++){
for(int j=0;j<y;j++){
data[i][j]=(i+1)*(j+1);
}
}
for(int i=0;i<x;i++){
for(int j=0;j<y;j++){
printf("%3i ",data[i][j]);
}
printf("\n");
}
return 0;
}
How can i access points of that array using pointers instead of data[i][j]?
I tried searching for answer but in every example I see people use data[x][y] option, i have to use pointers for accessing each element.
Also is error handling correct in that code?
if(!**data){
printf("Error");
return 1;
}
Here's a major problem, especially on 64-bit systems where sizeof(int) != sizeof(int *):
int **data = (int**) malloc(x * sizeof(int));
You allocate x times the size of int, not the size of pointer to int.
There is a good "trick" to always get the correct size, use sizeof *variable_youre_allocating_for. In your case it would be
int **data = malloc(x * sizeof *data);
This works because sizeof *data is done at compile-time, and the compiler knows that *data is of type int * and will use the correct size.
Also notice that I removed the cast, it's not needed in C.
Besides that, your use of the data is correct. Using data[i][j] is perfectly fine, if i and j are valid indexes, and data and data[i] have been properly initialized.
The important part is to remember that for any pointer or array a and index i, the expression a[i] is exactly equal to *(a + i). In fact, the compiler will translate a[i] to *(a + i). So for your pointer data, the expression *(data + i) is exactly equal to data[i]. And the latter is usually easier to read and understand, as well as less to write.
Related
I dynamically allocated memory for 3D array of pointers. My question is how many pointers do I have? I mean, do I have X·Y number of pointers pointing to an array of double or X·Y·Z pointers pointing to a double element or is there another variant?
double*** arr;
arr = (double***)calloc(X, sizeof(double));
for (int i = 0; i < X; ++i) {
*(arr + i) = (double**)calloc(Y, sizeof(double));
for (int k = 0; k < Y; ++k) {
*(*(arr+i) + k) = (double*)calloc(Z, sizeof(double));
}
}
The code you apparently intended to write would start:
double ***arr = calloc(X, sizeof *arr);
Notes:
Here we define one pointer, arr, and set it to point to memory provided by calloc.
Using sizeof (double) with this is wrong; arr is going to point to things of type double **, so we want the size of that. The sizeof operator accepts either types in parentheses or objects. So we can write sizeof *arr to mean “the size of a thing that arr will point to”. This always gets the right size for whatever arr points to; we never have to figure out the type.
There is no need to use calloc if we are going to assign values to all of the elements. We can use just double ***arr = malloc(X * sizeof *arr);.
In C, there is no need to cast the return value of calloc or malloc. Its type is void *, and the compiler will automatically convert that to whatever pointer type we assign it to. If the compiler complains, you are probably using a C++ compiler, not a C compiler, and the rules are different.
You should check the return value from calloc or malloc in case not enough memory was available. For brevity, I omit showing the code for that.
Then the code would continue:
for (ptrdiff_t i = 0; i < X; ++i)
{
arr[i] = calloc(Y, sizeof *arr[i]);
…
}
Notes:
Here we assign values to the X pointers that arr points to.
ptrdiff_t is defined in stddef.h. You should generally use it for array indices, unless there is a reason to use another type.
arr[i] is equivalent to *(arr + i) but is generally easier for humans to read and think about.
As before sizeof *arr[i] automatically gives us the right size for the pointer we are setting, arr[i].
Finally, the … in there is:
for (ptrdiff_t k = 0; k < Y; ++k)
arr[i][k] = calloc(Z, sizeof *arr[i][k]);
Notes:
Here we assign values to the Y pointers that arr[i] points to, and this loop is inside the loop on i that executes X times, so this code assigns XY pointers in total.
So the answer to your question is we have 1 + X + XY pointers.
Nobody producing good commercial code uses this. Using pointers-to-pointers-to-pointers is bad for the hardware (meaning inefficient in performance) because the processor generally cannot predict where a pointer points to until it fetches it. Accessing some member of your array, arr[i][j][k], requires loading three pointers from memory.
In most C implementations, you can simply allocate a three-dimensional array:
double (*arr)[Y][Z] = calloc(X, sizeof *arr);
With this, when you access arr[i][j][k], the compiler will calculate the address (as, in effect, arr + (i*Y + j)*Z + k). Although that involves several multiplications and additions, they are fairly simple for modern processors and are likely as fast or faster than fetching pointers from memory and they leave the processor’s load-store unit free to fetch the actual array data. Also, when you are using the same i and/or j repeatedly, the compiler likely generates code that keeps i*Y and/or (i*Y + j)*Z around for multiple uses without recalculating them.
Well, short answer is: it is not known.
As a classic example, keep in mind the main() prototype
int main( int argc, char** argv);
argc keeps the number of pointers. Without it we do not know how many they are. The system builds the array argv, gently updates argc with the value and then launches the program.
Back to your array
double*** arr;
All you know is that
arr is a pointer.
*arr is double**, also a pointer
**arr is double*, also a pointer
***arr is a double.
What you will get in code depends on how you build this. A common way if you need an array of arrays and things like that is to mimic the system and use a few unsigned and wrap them all with the pointers into a struct like
typedef struct
{
int n_planes;
int n_rows;
int n_columns;
double*** array;
} Cube;
A CSV file for example is char ** **, a sheet workbook is char ** ** ** and it is a bit scary, but works. For each ** a counter is needed, as said above about main()
A C example
The code below uses arr, declared as double***, to
store a pointer to a pointer to a pointer to a double
prints the value using the 3 pointers
then uses arr again to build a cube of X*Y*Z doubles, using a bit of math to set values to 9XY9.Z9
the program uses 2, 3 and 4 for a total of 24 values
lists the full array
list the first and the very last element, arr[0][0][0] and arr[X-1][Y-1][Z-1]
frees the whole thing in reverse order
The code
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int n_planes;
int n_rows;
int n_columns;
double*** array;
} Cube;
int print_array(double***, int, int, int);
int main(void)
{
double sample = 20.21;
double* pDouble = &sample;
double** ppDouble = &pDouble;
double*** arr = &ppDouble;
printf("***arr is %.2ff\n", ***arr);
printf("original double is %.2ff\n", sample);
printf("*pDouble is %.2ff\n", *pDouble);
printf("**ppDouble is %.2ff\n", **ppDouble);
// but we can build a cube of XxYxZ doubles for arr
int X = 2;
int Y = 3;
int Z = 4; // 24 elements
arr = (double***)malloc(X * sizeof(double**));
// now each arr[i] must point to an array of double**
for (int i = 0; i < X; i += 1)
{
arr[i] = (double**)malloc(Y * sizeof(double*));
for (int j = 0; j < Y; j += 1)
{
arr[i][j] = (double*)malloc(Z * sizeof(double));
for (int k = 0; k < Z; k += 1)
{
arr[i][j][k] = (100. * i) + (10. * j) + (.1 * k) + 9009.09;
}
}
}
print_array(arr, X, Y, Z);
printf("\n\
Test: first element is arr[%d][%d[%d] = %6.2f (9XY9.Z9)\n\
last element is arr[%d][%d[%d] = %6.2f (9XY9.Z9)\n",
0, 0, 0, arr[0][0][0],
(X-1), (Y-1), (Z-1), arr[X-1][Y-1][Z-1]
);
// now to free this monster
for (int x = 0; x < X; x += 1)
{
for (int y = 0; y < Y; y += 1)
{
free(arr[x][y]); // the Z rows
}
free(arr[x]); // the plane Y
}
free(arr); // the initial pointer;
return 0;
}; // main()
int print_array(double*** block, int I, int J, int K)
{
for (int a = 0; a < I; a += 1)
{
printf("\nPlane %d\n\n", a);
for (int b = 0; b < J; b += 1)
{
for (int c = 0; c < K; c += 1)
{
printf("%6.2f ", block[a][b][c]);
}
printf("\n");
}
}
return 0;
}; // print_array()
The output
***arr is 20.21f
original double is 20.21f
*pDouble is 20.21f
**ppDouble is 20.21f
Plane 0
9009.09 9009.19 9009.29 9009.39
9019.09 9019.19 9019.29 9019.39
9029.09 9029.19 9029.29 9029.39
Plane 1
9109.09 9109.19 9109.29 9109.39
9119.09 9119.19 9119.29 9119.39
9129.09 9129.19 9129.29 9129.39
Test: first element is arr[0][0[0] = 9009.09 (9XY9.Z9)
last element is arr[1][2[3] = 9129.39 (9XY9.Z9)
Is it possible to allocate dynamically and initialize (and free) a matrix (or others multidimensional arrays) using sizeof operator instead of indexes and "standard" pointer arithmetic?
I've tried this:
#include <stdio.h>
#include <stdlib.h>
#define ROWS 3
#define COLUMNS 4
int main(void)
{
int i, j;
char **v;
if((v = malloc(ROWS*sizeof(char*)))==NULL)
return -1;
for(i=0; i<ROWS; i++)
{
if((*(v + i * sizeof(char*)) = malloc(COLUMNS * sizeof(char)))==NULL)
return -2;
}
for(i=0; i<ROWS; i++)
{
for(j=0; j<COLUMNS; j++)
{
*(*(v + i * sizeof(char*)) + j * sizeof(char)) = 'a' + i * COLUMNS + j;
printf("%c",*(*(v + i * sizeof(char*)) + j * sizeof(char)));
}
}
for(i=0; i<ROWS; i++)
{
free(*(v + i * COLUMNS * sizeof(char)));
}
free(v);
return 0;
}
but it generates a core dump (SIGSEGV at line 24 (v[1][0])). I believe the problem is in the allocation (maybe for the allocation v[1], v[2]... v[ROWS] malloc goes to write on the memory first allocated). Precisely, what is the problem?
Thanks.
It's because *(v + i * sizeof(char *)) is equivalent to v[i * sizeof(char *)] or *((unsigned char *) v + i * sizeof(char *) * sizeof(char *).
In pointer arithmetic, the increment is performed in units of the pointee type, in this case char *.
If you want to compute the offset yourself just cast the pointer to unsigned char * but that,
Is absolutely redundant, except in some situations where you don't want the pointer to have a definite type and it's void *, in that case casting to unsigned char * and incrementing the exact number of bytes is OK.
There is no good reason for that to be a requirement, you don't use the sizeof operator because it's a requirement but instead because you need to.
It's error prone and you can easily cause Undefined Behavior as it happens with your code, which has something even more disturbing
*(*(v + i * sizeof(char*)) + j * sizeof(char))
In detail,
There is no way that sizeof(char) will be different than 1, it's like multiplying by sin2(x) + cos2(x), it makes absolutely no sense.
You are incrementing the pointer way beyond the allocated space, becauseof the first point again.
I need to re-size a malloc'd C array. However, I'm not supposed to use realloc() (it's for an assignment). The below code keeps throwing double free or corruption (out) More specifically, this function seems to do nothing, since the program behaves the same whether I call it or not. I feel like I'm probably missing something basic. Can anyone help me out? Thanks a lot
void double_array_size(float *array, int *size) {
float *temp = NULL;
int i;
temp = (float *) malloc(*size * 2 * sizeof(float));
for (i = 0; i < *size; i++) {
temp[i] = array[i];
}
*size *= 2;
free(array);
array = temp;
}
Like BLUEPIXY said, pass a double pointer or if you don't want to, better this:
float *double_array_size(float *array, int *size) {
float *temp = NULL;
int i;
temp = (float *) malloc(*size * 2 * sizeof(float));
for (i = 0; i < *size; i++) {
temp[i] = array[i];
}
*size *= 2;
free(array);
return temp;
}
and to increase the performance of you code, do not use a for loop, use memcpy instead:
temp = (float *) malloc(*size * 2 * sizeof(float));
memcpy(temp, array, sizeof *array * *size);
You should always check the return value of malloc and friends. They might return NULL and depending on your code, you might have to react to this if you don't want your code to crash.
Another thing: if you are using C only, do not cast malloc and I suggest to use sizeof *var instead of sizeof(float) because you are hardcoding the type. Let's say that you have to change the type of the array. If you hardcore your types, you have to change the types everywhere, otherwise only in the declarations, much less work and fewer errors.
Sometimes you need more or less the same code for different types. Luckily in C++ you have templates, in C you have to use Macros, if you don't want to repeat basically the same code over and over, for example:
#define DOUBLE_ARRAY_SIZE(type) \
type *double_array_size_ ##type (type *array, size_t *size) {\
type *temp; \
temp = malloc(*size * 2 * sizeof *array);\
if(temp == NULL)\
return NULL;\
memcpy(temp, array, sizeof *array * *size);\
*size *= 2;\
free(array);\
return temp;\
}
And instead of writing the same code with different types over and over, you can do
DOUBLE_ARRAY_SIZE(int)
DOUBLE_ARRAY_SIZE(double)
DOUBLE_ARRAY_SIZE(record_t)
void foo()
{
int *ints = malloc(...);
record_t *recs = malloc(...);
...
new_ints = double_array_size_int(ints, ints_size);
new_recs = double_array_size_record_t(recs, recs_size);
....
}
I know that a lot of people will say do not use macros, they're evil and they are kind of true, but using them wisely may help you more thank you think. One of the reason you should try to hardcore the datatype as less as possible.
// edit my macro snippet, chux's suggestion with size_t
One problem with this code is that parameters are call-by-value, so you’re changing only the local copy of array and leaking memory. The value in the rest of the program is never updated. What you want to do is return the reallocated array.
I want to create a bidimensional array like so:
void **mdeclaraMatrice(int nrLini,int nrColoane, int sizeOfElement)
{
int i;
void **m = malloc(nrLini * 4);
if(m==NULL)
return NULL;
for(i=0; i<nrLini; i++)
{
*(m + (i*4)) = malloc(nrColoane * sizeOfElement);
if(*(m + (i*4)) == NULL)
return NULL;
}
return m;
}
I whant to use it like this:
int **m = (int **)mdeclaraMatrice(n,m,sizeof(int));
but it doesn't work. What do I do wrong?
You should use m[i] instead of *(m+i*4) and let the compiler do the arithmetic.
In addition, you should deallocate the already-allocated memory in case of a failure.
Try this instead:
void **mdeclaraMatrice(int nrLini, int nrColoane, int sizeOfElement)
{
int i;
void **m = malloc(nrLini * sizeof(void*));
if (m == NULL)
return NULL;
for (i=0; i<nrLini; i++)
{
m[i] = malloc(nrColoane * sizeOfElement);
if (m[i] == NULL)
{
while (i-- > 0)
free(m[i]);
free(m);
return NULL;
}
}
return m;
}
[not an answer to the question, but to the indented usage of the proper answer as given by others]
To access the void pointer array as an array of int, doing this
int **m = (int **)mdeclaraMatrice(n,m,sizeof(int));
is not correct, as per the C-Standard only void* converts to any other pointer properly, void** doesn't necessarily. So it shall correctly be
void ** ppv = mdeclaraMatrice(n,m,sizeof(int));
int * pi = *ppv; /* Please note, there is NO casting necessary here! */
Then access the members like so:
pi[0] = 42
pi[1] = 43;
...
Which essently is the same as doing
*((int *) (pi + 0)) = 42;
*((int *) (pi + 1)) = 43;
which indeed does not make sense really as pi already is int*, so the fully correct approach (also taking into account the 2nd dimension) would be:
((int *)(ppv[0]))[0] = 42;
((int *)(ppv[0]))[1] = 43;
Which could be made usable by definging a macro:
#define GENERIC_ARRAY_ELEMENT(type, address, r, c) \
((type *)(address[r]))[c]
GENERIC_ARRAY_ELEMENT(int, ppv, 0, 0) = 42;
GENERIC_ARRAY_ELEMENT(int, ppv, 0, 1) = 43;
I will address the problem of allocation an array of void pointers and then interpreting them as an array of int pointers.
int **nope = (int **)mdeclaraMatrice(n,m,sizeof(int));
Even assuming the allocation was completely correct the assignment and later usage of nope is undefined behavior. void** and int** have incompatible types.
What you can do is the following. Assign the void pointers one by one to an array of int pointers.
void** arrp = mdeclaraMatrice(n,m,sizeof(int));
int* arr[n] ;
for( size_t i = 0 , i < n ; i++ )
arr[i] = arrp[i] ;
And then use the arr array, When you want to free the memory you free the original pointer:
free( arrp ) ;
The problem occurs in this line:
*(m + (i*4)) = malloc(nrColoane * sizeOfElement);
You have to know that when adding a number to an address, the address will be incremented by the number times the size of the object the address points to. So if your pointer points to an object that is of size 4 bytes, and you add 1 to it, then the address will automatically be incremented by 4, not by 1. So you should abandon *4.
Also, use the sizeof operator when allocating space, because addresses (and thus pointers) can have different sizes on different processor architectures.
Actually, you don't even need your generic 2D array function if you know the powerfull VLA features of C99. To allocate a true 2D array (no index array required), you just do this:
int (*twoDIntArray)[width] = malloc(height*sizeof(*twoDIntArray));
That's it. Accesses are just as simple:
twoDIntArray[line][column] = 42;
In this code, twoDIntArray is a pointer to an array of width integers. The malloc() call simply allocates enough space for height such line arrays. When you do the pointer arithmetic twoDIntArray[line], you add the size of line line arrays to the pointer, which produces the address of the corresponding line array. This line array is then indexed by the second array subscript [column].
Needless to say that freeing such an array is just as trivial:
free(twoDIntArray);
I don't understand why this works:
void main() {
int * b;
b = (int *)malloc(sizeof(int));
*b = 1;
printf("*b = %d\n", *b);
}
while this does not (gets segmentation fault for the malloc()):
void main() {
int ** a;
int i;
for (i = 0; i<= 3; i++) {
a[i] = (int*)malloc(sizeof(int));
*(a[i]) = i;
printf("*a[%d] = %d\n", i, *(a[i]));
}
}
since I find a[i] is just like b in the first example.
BTW, a[i] is equal to *(a+i), right?
You need to allocate memory for a first, so that you can access its members as a[i].
So if you want to allocate for 4 int * do
a = malloc(sizeof(int *) * 4);
for (i = 0; i<= 3; i++) {
...
}
or define it as array of integer pointers as
int *a[4];
a is a 2 dimensional pointer, you have to allocate both dimension.
b is a 1 dimensional pointer, you have to allocate only one dimension and that's what you're doing with
b = (int *)malloc(sizeof(int));
So in order the second example to work you have to allocate the space for the pointer of pointer
void main() {
int ** a;
int i;
a = (int**)malloc(4*sizeof(int*));
for (i = 0; i<= 3; i++) {
a[i] = (int*)malloc(sizeof(int));
*(a[i]) = i;
printf("*a[%d] = %d\n", i, *(a[i]));
}
The allocated pointer is written to uninitialized memory (you never set a to anything), causing undefined behavior.
So no, it's not at all equivalent to the code in the first example.
You would need something like:
int **a;
a = malloc(3 * sizeof *a);
first, to make sure a holds something valid, then you can use indexing and assign to a[0].
Further, this:
a[i] = (int*)malloc(sizeof(int));
doesn't make any sense. It's assigning to a[i], an object of type int *, but allocating space for sizeof (int).
Finally, don't cast the return value of malloc() in C.
actually malloc it's not that trivial if you really want safe and portable, on linux for example malloc could return a positive response for a given request even if the actual memory it's not even really reserved for your program or the memory it's not writable.
For what I know both of your examples can potentially return a seg-fault or simply crash.
#ruppells-vulture I would argue that malloc is really portable and "safe" for this reasons.