I'm having a problem understanding the realloc function in C - c

Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int* cut(int* x, int n);
int main() {
int *x= NULL,n;
x = malloc(sizeof(int));
printf("Amount of elements: ");
scanf("%d", x);
x = realloc(x, (*x+1) * sizeof(int));
assert(x != NULL);// allocate memory and ensure that this was successful
for (int i = 1; i <= *x; i++) {
printf("%d Element: ", i);
scanf("%d", x+i);
}
printf("pper barrier: ");
scanf("%d", &n);
x = cut(x,n);
for (int i = 1; i <= *x; i++) {
printf("%d ", *(x+i));
}
printf("\n");
free(x);
}
int* cut(int *x, int n) {
int a = 1;
for (int i = 1; i <= *x; i++) {
if(*(x+i) < n) {
*(x+a) = *(x+i);
a++;
}
}
*x = a-1;
x = realloc(x, (a+1) * sizeof(int));
return x;
}
The code works fine however I do not unterstand the line x = realloc(x, (*x+1) * sizeof(int)); Furthermore I don't get why the first x has no * but the second (*x+1) has one. Does this mean a pointer of the pointer?
I think it just means that the array malloc that was made is getting bigger by one value However I'm not sure and a still a bit confused what that actually means, could someone please help me out and clarify my missunderstanding?

x = realloc(x, (*x+1) * sizeof(int));
Let's start with this part:
x = realloc(x, ...
The code is calling realloc and passing as the first parameter whatever x points to and storing the result in x. That means that the block currently pointed to by x will be resized and the result stored in x. So x will point to a resized version of whatever x pointed to before.
The (x + 1) * sizeof(int) is the size of the block. Let's start with the right side, * sizeof(int). That means enough space to store some number of ints. How many ints? *x + 1 of them.
So this means to change x to point to a resized version of the block x already pointed to, resizing the block to hold one more integer than the value of the integer x points to.

scanf("%d", x);
This sets the integer at the address x to the value that the user typed. For example, if the user types 3, this line does the equivalent of *x = 3;.
x = realloc(x, (*x+1) * sizeof(int));
*x is dereferencing x, not making a pointer to x (that would be &x). So it's the value that the user typed. So this line makes x point to an array of N+1 elements, where N is the value that the user typed. (Assuming the memory allocation succeeds.)
Later, in cut,
*x = a-1;
x = realloc(x, (a+1) * sizeof(int));
these two lines again maintain the invariant that the first element of the array is the number of elements that follow.

I do not unterstand the line x = realloc(x, (*x+1) * sizeof(int));
x is an int*. *x dereferences x (so that you get the value entered by the user in the previous scanf("%d", x);). So, (*x + 1) means, "the value entered by the user plus one". Take that and multiply it with the size of an int. The x argument to realloc is the pointer with a prior allocation that you want to increase the allocated memory for. The returned pointer (that may be the same or a new value as the prior x) is then assigned to x.
Furthermore I don't get why the first x has no * but the second (*x+1) has one. Does this mean a pointer of the pointer?
x = ... means "assign a value to x". realloc returns a void* which can be implicitly converted to any pointer type, like an int*, and x is an int*.
In (*x + 1) the * is used to dereference x, that is, fetch the value of the int that x is pointing at.

Related

How to allocate memory equal in size to a variable read from an input file?

I'm building a code to simulate the response of some dynamical systems for my PhD. Basically what I'm trying to do is:
Ask the user for the name of a input file that contains all parameters for the simulation;
Read the input file and assign each parameter to a specific variable in my program.
Do the calculations.
I'm having problems on step 2, as one of the values in the input file is the dimension dim of an dinamically allocated array *x.
Here is a working example of the code:
#include <stdio.h>
#include <stdlib.h>
void read_file(char *name, int *dim, double **x) {
// Open input file
FILE *input = fopen(name, "r");
if (input == NULL) {
// Return error
perror(name);
return;
}
// Read and assign system constants
fscanf(input, "%i", dim);
printf("dim = %i\n", *dim);
// Allocate memory for x[dim]
*x = malloc((*dim) * sizeof(*x));
double y[(*dim)];
printf("size of (*x) = %llu\n", sizeof(*x));
printf("size of y = %llu\n", sizeof(y));
// Security check for pointers
if(*x == NULL) {
free(*x);
printf("Memory allocation for *x did not complete successfully\n");
return;
}
// assign values to x[dim] vector
for (int i = 0; i < *dim; i++) {
fscanf(input, "%lf", &(*x)[i]);
printf("(*x)[%i] = %lf\n", i, (*x)[i]);
}
// Close input file
fclose(input);
}
char *get_input_filename(void) {
char *filename = malloc(200 * sizeof(*filename));
printf("Enter Input Filename: ");
scanf("%s", filename);
return filename;
}
int main (void) {
int DIM;
double *x = NULL;
char *input_filename = get_input_filename();
read_file(input_filename, &DIM, &x);
printf("size of (*x) = %llu\n", sizeof(*x));
for (int i = 0; i < DIM; i++) {
printf("(*x)[%i] = %lf\n", i, x[i]);
}
free(x); free(input_filename);
}
And here is the content of the input file in.txt for this example:
5
0.0 0.1 0.2 1.4 2.6
When I call *x = malloc((*dim) * sizeof(*x)); I expected to find the dimension of the system to be 5 * 8bytes, as the value for *dim is assigned in the previous line, however only 8 bytes are allocated. Then, I declared the y[(*dim)] variable to check if the sizeof a VLA would behave in the same way as the sizeof *x, just to compare. The sizeof(y) was what I expected, but the sizeof(*x) wasn't, as shown in the output:
Enter Input Filename: in.txt
dim = 5
size of (*x) = 8
size of y = 40
(*x)[0] = 0.000000
(*x)[1] = 0.100000
(*x)[2] = 0.200000
(*x)[3] = 1.400000
(*x)[4] = 2.600000
size of (*x) = 8
(*x)[0] = 0.000000
(*x)[1] = 0.100000
(*x)[2] = 0.200000
(*x)[3] = 1.400000
(*x)[4] = 2.600000
I understand that it cannot allocate memory if the value of *dim is unknown, but a value is assigned in the previous line.
Also, I even don't know how the program assigned values to (*x) successfully as it don't have the necessary allocation of bytes to do it.
What am I missing here? How can I allocate the memory correctly?
Thanks in advance
Both dim and x are output arguments; pointers that refer to locations where you're to store your results of this function (a size and a memory allocation sequence of double values).
This is where things are going off the rails:
*x = malloc((*dim) * sizeof(*x));
The left side is ok. And so is most of the right side. But if you're ever allocating to a pointer based on the size of the dereferenced data a pointer points to, you need to do so using just that: the size of the thing the pointer points to. x is a pointer-to-pointer, *x is a pointer, and the latter is the 'thing' we're allocating memory for, the address of which will be stored at *x.
Therefore, that should be:
*x = malloc((*dim) * sizeof **x);
Note: when I'm using variables as the operator argument for sizeof I personally strive not to use parens. It ensures I'm actually using a variable id rather than a type id, since the latter isn't allowed without parens. use what you favor at your discretion/whim.
More fundamental, however, your familiarity and understanding of sizeof is wrong and/or misled. You cannot acquire the size of dynamic-allocated memory region using sizeof. Using the sizeof operator on a pointer variable will give you exactly what you asked for: the size of the pointer variable (e.g. the size of a pointer). It is your responsibility to maintain and track magnitude of dynamic allocations (which, btw, your code does, using dim).

How many pointers are in an array of pointers

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)

Calling a void function to add two numbers then dealing with the pointer of the sum

My objective is to call a void function "sum" which is passed two integers where they will be added together. I then want the first integer variable to be modified so that it is pointing at the sum of the two integers.
When I compile I get "error: indirection requires pointer operand ('int' invalid)."
This should work:
void sum(int *x, int y){
*x += y; // *x means "contents of what is pointed to by pointer x"
}
void call_sum() {
int x = 1, y = 2;
sum(&x,y); // &x because you're passing the address
printf("%d\n", x); // this should print 3
}
In that case you want:
void sum ( int * x, int y ) {
if (x != NULL) *x += y;
}
...
sum(&x, y);
Saying int * y says you need to pass the address of an int variable. The & character is the address-of operator.
In the function *y says use the value at the address, not the address itself.
The if (x != NULL) check is because, without it doing:
sum(NULL, x);
is "undefined behavior" (think Allstate "Mayhem" commercial) :)

Generic bidimensional 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);

What does this C function do?

double *f(int n, double v)
{
double *a, *p;
a = malloc(n * sizeof(double));
if (a != NULL)
for (p = a; p < a + n; p++)
*p = v;
return a;
}
Can you explain me what this function is needed for? Does it copy the content of v in n? If yes, why does it return a? I really don't get it... Thanks in advance.
It returns a newly allocated double array of size n filled with value v, or NULL if the allocation fails.
This loop:
for (p = a; p < a + n; p++)
*p = v;
uses pointer arithmetic. As p is a pointer to a double, incrementing it will point to the next double to write. *p = v writes the double at the specified location.
double *f(int n, double v)
{
double *a, *p;
a = malloc(n * sizeof(double)); // allocate memory enough for "n" doubles (an array)
if (a != NULL) // if the allocation was successful
for (p = a; p < a + n; p++) // loop from the beginning of the array to the end
*p = v; // fill every element of the array with the value "v"
return a; // return the new array
}
So if I called this function:
double * myarray;
myarray = f(3, 1.3);
Now I have:
myarray[0] = 1.3
myarray[1] = 1.3
myarray[2] = 1.3
So to answers your questions:
Can you explain me what this function is needed for?
allocates and initializes an array of doubles.
Does it copy the content of v in n?
No. Considering v is a double and n is an int, that doesn't even make sense. It makes an array n large and initializes it with the value v.
If yes, why does it return a?
It returns a so you have a reference to the newly created array. (see example above on how it could be used)
It allocates an array of n doubles, initialising each element of the array to the value of v.
The function returns a to allow the caller to use this newly allocated array.
It allocs a memory area of n * sizeof(double) bytes and enterely fill it with v value
Allocate an array of n doubles in heap, fill it with v and return the pointer to it?
Duplicate the v n times into an array of float
The array is allocated in the function and contains n float elements.
at the end of the function each element in the array a is containing v as value

Resources