c - dynamic memory - c

Hi everyone out there very first thanks to all of you for providing help.
Now i want to know about double pointer. I'm doing code like this:
int main()
{
int **a;
a = (int*)malloc(sizeof(*int)*5);
for (i=0;i<5;i++)
{
a[i] = malloc(sizeof(int)*3);
}
}
Now i dont know if I'm doing it right. How can I put values in this type of array ? Can anybody explain this concept with example ? Thanks in advance.

Well, you have allocated an array equivalent in size to:
int a[5][3];
So to enter values you just do like this:
a[0][0] = 1234;
Which would put a value into the first column of the first row and
a[4][2] = 9999;
would put another value into the last column of the last row.
Since you are using malloc, you should also loop through a[i] from i = 0 to 4, and free(a[i]); and then free(a); or your program will leak memory.

All right... what you have here, basically, is a pointer-pointer, namely, the adress of an adress. You can use this kind of variable when dealing with arrays.
The first two lines of your code are equivalent to :
int* a[5]; // Declaration of an array of 5 integer pointers (a[0] till a[4]).
A "pure" C code doesn't use variable for the size of an array, so you use the malloc when you want to edit dynamically the size of the array.
Meaning, if in your code, you are not going to change the size of your arrays, you are using a very complex way to achieve a very simple goal. You could just type :
int a[5][3];
But if you do not know the size of your array, you have to use the mallocs (and then, free). What you are doing, basically, is :
Declaring an array of array;
Allocating the memory for x number of POINTER to integer arrays;
For each of these POINTERS, allocating memory for y integers.
Now that you have done this, you can use your arrays normally. For instance :
a[1][0] = 1;
will mean : in the first array [1], the first row [0] is 1.
The only difference with a standard declaration like the one above, without the mallocs, is that since you allocated memory, you'll have to free it. Which is why you don't want to lose your variable a**. At the end of your function, the pointer-to-pointer variable will be destroyed, but not the memory you allocated.

Related

Initially mallocate 0 elements to later reallocate and measure size

I have a function that will add a new position to an array by reallocating new memory every time it is called.
The problem is that, for each call I need it to add one position to the array, starting from 1 at first call, but I understand that I have to mallocate before reallocating.
So my question is, can I initially do something like p = malloc(0) and then reallocate for example using p = (int *)realloc(p,sizeof(int)) inside my function? p is declared as int *p.
Maybe with a different syntax?
Of course I could make a condition in my function that would mallocate if memory hasn't been allocated before and reallocate if it has, but I am looking for a better way.
And the second problem I have is... Once reallocated more positions, I want to know the size of the array.
I know that if, for example, I declare an array a[10], the number of elements would be defined by sizeof(a)/sizeof(a[0]), but for some reason that doesn't work with arrays declared as pointers and then reallocated.
Any advice?
You could initialize your pointer to NULL, so that the first time you call realloc(yourPointer, yourSize), it will return the same value as malloc(yourSize).
For your second problem, you could use a struct that contains your pointer and a count member.
struct MyIntVector {
int * ptr;
size_t count;
}
Then you probably will want to define wrapper functions for malloc, realloc, and free (where you could reset ptr to NULL), that takes your struct as one of the parameters, and updates the struct as needed.
If you want to optimize this for pushing 1 element at a time, you could add a allocatedCount member, and only realloc if count == allocatedCount, with a new allocatedCount equals (for example) twice the old allocatedCount.
You should implement this in a MyIntVector_Push(MyIntVector *, int ) function.
You will then have a simplified c version of c++ std::vector<int> (but without automatic deallocation when the object goes out of scope).
As ThreeStarProgrammer57 said just use realloc.
realloc(NULL, nr_of_bytes) is equivalent to malloc(nr_of_bytes)
so
p = realloc(p, your_new_size)
will work just fine the first time if p is initialized to NULL. But be sure to pass the number of bytes you need after resizing, not the additional space that you want, as you have written your question.
As regarding the size, you have to keep track of it. That's the way C was designed.

Structures for beginners

I am new to structures and I'm trying to do some tutorials to see if i understood well what i've been learning. Here's the code I wrote:
#include <stdio.h>
#include <stdlib.h>
typedef struct variables{
float Vx;
float Vy;
float Vz;
}velocity;
int main(){
velocity *pv;
pv = (velocity*)malloc(sizeof(velocity));
pv[0].Vx = 1;
pv[0].Vy = 2;
pv[0].Vz = 3;
free(pv);
return 0;
}
So my questions are 2:
Did I allocate the three variables in correct way?
Since I'm using the array notation why should I ever write [0]
instead of [1] or [2] or so on?
To answer the first question: yes, your code is completely correct. (You even free'd it properly, I'm a bit proud!)
As for the second question, I'm a bit unsure what you mean, but when you call malloc(N * sizeof(type)) where N is some integer (in your case, it would just be 1), you are in essence just creating an array of N elements of type. So pv[0] is the first and only element in this array when N=1, and pv[1], pv[2] etc don't exist.
You should, however, use the syntax pv->Vx instead of pv[0].Vx.
Your code is correct, but the syntax you are using is a bit odd. The operator [n] means: Take the pointer's address (in your case the value in pv), increment it by n, and dereference it. Since you are not incrementing the address (n = 0), you can just dereference it. You do this with *pv, or simply with pv->. You only need the [] operator when you have allocated more than one struct, and want to set the address to one of these structs. pv[3] would then be the same as *(pv+3). But you first have to allocate more space if you want to use a pointer as an array:
malloc(sizeof(velocity) * 4)
Yes, you used your variables in proper way.
in your code, you've only allocated memory for one instance of the variable. so, it's same if you write pv[0].Vx or pv->Vx. If you want to allocate memory for n number of instances, you can use pv[k].Vx, where 0<=k<=n-1.
SideNote: Please do not cast the return value of malloc().

Syntax Error : '{'

I am writing a C program that uses an array of integers which is a part of a structure. The structure is:
struct test
{
int *ques;
int a;
int b;
int len; // len is the length of the array defined in the structure as ques.
};
In a function after this declaration I have assigned a value to the len as:
cases[0].len=5; // here cases is an array of the type struct test.
and then I have used malloc to allocate memory to the array member ques as follows:
cases[0].ques=(int *)malloc(cases[counter].len*sizeof(int));
After that I have tried to fill in the array ques as follows:
cases[0].ques[5]={-7,-6,-5,-4,-3};
and while compiling I get an error at the above line stating that:
maxmin.c(47) : error C2059: syntax error : '{'
Can you please help me out?
This is invalid: cases[0].ques[5]={-7,-6,-5,-4,-3};
You can initialize an array in C this way, only at the time of declaration of array.
To fill in the values at this point in your C program you should use for loop to fill every index separately.
Right now the C compiler parses this statement as:
Value of index 5 of array ques at index 0 of structure array cases of type struct test is {-7,-6,-5,-4,-3}, which is certainly invalid since you cannot use { while assigning a value to a variable.
Update at OP's comment:
You can keep all the values in temp array say int temp[50] = {...}; then after allocating space to ques you can use memcpy function to copy len number of values to ques.
If you have C99 or C11, you can use a compound literal in conjunction with memcpy() or memmove() to initialize the new array:
memmove(&cases[0].ques, (int []){-7,-6,-5,-4,-3}, 5 * sizeof(int));
This also fixes the problem that you allocate cases[0].ques as a pointer to 5 integers, but you then try to assign to a single element that is beyond the end of the allocated array. The code is also inconsistent in that most of it references cases[0] but the malloc() call references cases[count] in the argument list. Not automatically wrong, but definitely unusual.
The array literal can be as big as you need. The only tricky bit is the size argument (third argument) to memmove(). I ducked fast on that; repeating the compound literal doesn't feel like the right move, but manually counting isn't a good solution either.
Well, you could if memmove() wasn't a macro that objected to being given 7 arguments instead of 3 (GCC 4.8.2 on Mac OS X 10.9.2)!
(memmove)(&cases[0].ques, (int []){-7,-6,-5,-4,-3}, 5 * sizeof(int));
memmove(&cases[0].ques, ((int []){-7,-6,-5,-4,-3}), 5 * sizeof(int));
The first invokes the function memmove(), not a macro. The second creates a single argument by wrapping parentheses around the compound literal. Both compile.
Note that although the compound literal looks like a cast and a brace-initializer, I'm not sure it is strictly a cast — it is best not to think of it as a cast but as a compound literal.
Incidentally, if the objective is to add N random values to an array of N integers (as mentioned in a comment to one of the other answers), then you won't want to use this technique — the integers in the example are implausible as a random sequence. If you do want 50 random numbers in some range, you'll use a random number generator (possibly rand(), possibly
lrand48(), possibly something else) to create the values in an appropriate range, using a simple for loop to initialize the correct number of array elements.
assign value to each array element as,
cases[0].ques[0]=-7
cases[0].ques[1]=-6
...
cases[0].ques[5]=-3
since you are assigning the value after declaration. C allows {} use for initializing array at the time of declaration. not after that.
I hope you realize why cases[0].ques[5] is wrong.
int arr[5] = {1,2,3,4,5};
The above code works because you are doing the initialization of array at the declaration time.
If you have
int arr[5];
arr[5] = {1,2,3,4,5}; // THIS WONT WORK
Here, you'll have to use for loop and fill each index.
also, when you do
int arr[5];
arr[5] = {1,2,3,4,5};
In the above code, what you are trying to do is, put some value in arr[5]. That is just one index of the entire array.
Additionally, as the comment suggests, arr[5] is the 6th element in the array of size 5. Now although it won't give error, but be prepared to get some unexpected results. :)
ques[5] is an int, you cannot assign an array to it
Also, C doesn't allow to assignment to multiple elements in an array like that. You can only do it at initialization. So create a new array and initialize with those 5 elements and copy it to your destination with memcpy() or memmove()
int[] tmp = {-7,-6,-5,-4,-3};
memcpy(cases[0].ques, tmp, 5*sizeof(int));
Alternatively you can assign values to ques[i] separately
Lot of time I do not program in C, but I think the only situation in which you can do a complete array declaration is in the time that you declare it:
int a[] = {...}
But not this way:
int a[5];
a = {...};
Also, in your case, you are doing
int a[5] = {...}
and this means that you are trying to assign an array to an integer.
Also, it's better if you do not do a cast in the malloc call:
cases[0].ques = malloc(cases[counter].len * sizeof(int));
cases[0].ques[5]={-7,-6,-5,-4,-3};
You cannot do this, this initializer only valid when you define an array.
You should do something like:
for (start = -7, i = 0; i < cases[0].len; i++, start++) {
cases[0].ques[i] = start;
}

Access two-dimensional array via pointer to first element

I got strucure
typedef struct
{char *cells;}
Map;
and cells suppose to be pointer to array of rows(in rows are integers on every position).
I don't know how to access for example to number on 3. position in 2. row.
I have stared with some array[3][3], but I don't know how to connect them with this struct.
I tried
Map nextmap;
nextmap.cells[0] = array[0][0];
But I got only first number, which is clear. How can I get to other positions?
Thanks in advance.
EDIT: renaming the structure ..
.
When you did Map nextmap;, you created an uninitialized Map struct. When you did nextmap.cells[0] = array[0][0]; you dereferenced (i.e. followed) the uninitialized pointer, and stored a value at the random memory it points at.
If you want to initialize the cells structure, you can do something as simple as nextmap.cells = array[0]; That will cause nextmap.cells to point at array. Note that it's not copying the contents; just pointing at them. That means that if you change the values through cells, you'll be modifying the values in arrays.
(Also, using 'new' as a variable name is perfectly acceptable in C, but you're likely to confuse any C++ programmers reading your code, since 'new' is an operator in that language.)
new now changed to nextmap in question
Edited to correct the type mismatch in nextmap.cells assignment.
Given an array char array[][NumberOfColumns] (the first dimension is irrelevant and is omitted here; it would be needed when the array is defined), you can set a pointer to the first element of the array with:
nextmap.cells = &array[0][0];
Then you can access an element in the array, array[i][j], by calculating its position within the array, with either of these two expressions:
*(nextmap.cells + i*NumberOfColumns + j)
nextmap.cells[i*NumberOfColumns + j]
Two-dimensional arrays generally ought to be addressed as two-dimensional arrays. Calculating the position manually is poor practice if done without good reason. If this school assignment did not have a good reason for this, then it is a bad assignment.
First of all new is not a good name for a variable.
new now changed to nextmap in question
Second of all in your case cells should be a double pointer, like this
char ** cells;
Or a pointer to a 2D array, like
char (*cells)[N][N];
where N is a constant you want to use.

Dynamic Array printing

I am trying to print a dynamic array, but I am having trouble with the bounds for the array.
For a simple example, lets say I'm trying to loop through an array of ints. How can I get the size of the array? I was trying to divide the size of the array by the size of the type like this sizeof(list)/sizeof(int) but that was not working correctly. I understand that I was trying to divide the size of the pointer by the type.
int *list
// Populate list
int i;
for(i = 0; i < ????; i++)
printf("%d", list[i]);
With dynamic arrays you need to maintain a pointer to the beginning address of the array and a value that holds the number of elements in that array. There may be other ways, but this is the easiest way I can think of.
sizeof(list) will also return 4 because the compiler is calculating the size of an integer pointer, not the size of your array, and this will always be four bytes (depending on your compiler).
YOU should know the size of the array, as you are who allocated it.
sizeof is an operator, which means it does its job at compile time. It will give you the size of an object, but not the length of an array.
So, sizeof(int*) is 32/62-bit depending on architecture.
Take a look at std::vector.
There is no standardized method to get the size of allocated memory block. You should keep size of list in unsigned listSize like this:
int *list;
unsigned listSize;
list = malloc(x * sizeof(int));
listSize = x;
If you are coding in C++, then it is better to use STL container like std::vector<>
As you wrote, you really did tried to divide the size of a pointer since list is declared as a pointer, and not an array. In those cases, you should keep the size of the list during the build of it, or finish the list with a special cell, say NULL, or anything else that will not be used in the array.
Seeing some of the inapropriate links to C++ tools for a C question, here is an answer for modern C.
Your ideas of what went wrong are quite correct, as you did it you only have a pointer, no size information about the allocation.
Modern C has variable length arrays (VLA) that you can either use directly or via malloc. Direcly:
int list[n];
and then your idea with the sizeof works out of the box, even if you changed your n in the mean time. This use is to be taken with a bit of care, since this is allocated on the stack. You shouldn't reserve too much, here. For a use with malloc:
int (list*)[n] = malloc(*list);
Then you'd have to adapt your code a bit basically putting a (*list) everywhere you had just list.
If by size you mean the number of elements then you could keep it in a counter that gets a ++ each time you push an element or if you dont mind the lost cycles you could make a function that gets a copy of the pointer to the first location, runs thru the list keeping a counter until it finds a k.next==null. or you could keep a list that as a next and a prev that way you wouldnt care if you lost the beginning.

Resources