I have some confusions/problems about the usage of pointers in C. I've put the example code below to understand it easily. Please notice differences of these codes. If you have some problem understanding it, please have a feedback.
This doesn't work.
#include <stdio.h>
#include <stdlib.h>
void process() {
int *arr;
arr=(int*)malloc(5*sizeof(int));
arr=(int*){3,1,4,5,2};
for(int z=0;z<5;z++) {
printf("%d ",arr[z]);
}
printf("\n");
}
int main() {
process();
return 0;
}
But this works.
#include <stdio.h>
#include <stdlib.h>
void process() {
int *arr;
arr=(int*)malloc(5*sizeof(int));
arr=(int[]){3,1,4,5,2};
for(int z=0;z<5;z++) {
printf("%d ",arr[z]);
}
printf("\n");
}
int main() {
process();
return 0;
}
This also works too. Why? I didn't allocate memory here.
#include <stdio.h>
#include <stdlib.h>
void process() {
int *arr;
arr=(int[]){3,1,4,5,2};
for(int z=0;z<5;z++) {
printf("%d ",arr[z]);
}
printf("\n");
}
int main() {
process();
return 0;
}
Why aren't they same?
arr=(int*){3,1,4,5,2};
arr=(int[]){3,1,4,5,2};
Is there any other way to initializing array of integer pointer, not using in this individual assigning way?
arr[0]=3;
arr[1]=1;
arr[2]=4;
arr[3]=5;
arr[4]=2;
How can i get the size/number of allocation in memory of pointer so that i can use something like for(int z=0;z<NUM;z++) { instead of for(int z=0;z<5;z++) { statically?
Any answer is highly appreciated.
Thanks in advance.
The malloc calls in the first few examples allocate a block of memory and assign a pointer to that memory to arr. As soon as you assign to arr again, the pointer value is overwritten, and you've lost track of that allocated memory -- i.e., you've leaked it. That's a bug right there.
In other words, if you allocate a block of memory using using malloc(), then you can write data into it using array syntax (for example):
int* arr = (int *) malloc(sizeof(int) * 5);
for (int i=0; i<5; ++i)
arr[i] = i;
But you can't assign anything else directly to arr, or you lose the pointer to that block of memory. And when you allocate a block using malloc(), don't forget to delete it using free() when you don't need it anymore.
An array is not a pointer-to-integer; it's an array. An array name is said to "decay to a pointer" when you pass it as an argument to a function accepting a pointer as an argument, but they're not the same thing.
Regarding your last question: that's actually the difference between an array and a pointer-to-type: the compiler knows the size of an array, but it does not know the size of a block pointed to by an arbitrary pointer-to-type. The answer, unfortunately, is no.
But since you're writing C++, not C, you shouldn't use arrays anyway: use `std::vector'! They know their own length, plus they're expandable.
When you say: ptr = {1,2,3,4,5}, you make ptr point to a memory in the data segment, where constant array {1,2,3,4,5} resides and thus you are leaking memory. If you want to initialize your memory, just after allocation, write: ptr[0]=1; ptr[1]=2; and so on. If you want to copy data, use memcpy.
The comma-separated list of values is a construct for initializing arrays. It's not suitable for initializing pointers to arrays. That's why you need that (int[]) - it tells gcc to create an unnamed array of integers that is initialized with the provided values.
gcc won't let you losing the information that arr is an array unless you really want to. That's why you need a cast. It's better that you declare arr as an array, not as a pointer. You can still pass it to the functions that accept a pointer. Yet gcc would not let you leak memory with malloc:
error: incompatible types when assigning to type ‘int[5]’ from type ‘void *’
If you want a variable that can be either an array or an pointer to allocated memory, create another variable for that. Better yet, create a function that accepts a pointer and pass it either an array or a pointer.
Related
I saw the following code:
#include <stdlib.h>
void foo(char n)
{
int (*vals)[n] = malloc(sizeof(int[n]));
for (int i = 0; i < n; ++i)
(*vals)[i] = i;
free(vals);
}
int main(int argc, char **argv)
{
foo(*(argv[1]));
return 0;
}
This lines makes me very uncomfortable:
free(vals);
vals is a pointer pointing to an array. This looks right, but I just have a difficult time internalizing it, I do not know why.
I am more used to the following style:
int *p = (int*)malloc(n * sizeof(int));
......
free(p);
In this code, p is a pointer pointing to the start of a memory region for some integers, the malloc and free are symmetric in that they both work on a pointer type; yet the original code has malloc() working on a pointer to an array and free() a pointer.
Out of curiosity, I modified the original code:
free(vals); ==> free(*vals);
I was expecting this change will fail at compiler, the reason is *vals is an array now. But gcc is fine and valgrind does not complain memory leak.
I know C has a thing called array degenerates to pointer at function call. But I just cannot internalize this stuff. Sorry writing so long to describe a problem, wish you could see my struggle. Is there a definitive doc/stackoverflow/blog to clear this up - best C99 or later?
Thanks!
writing free(*vals); is same as writing free(vals);
edited your code to clear that a little bit
#include <stdlib.h>
#include <stdio.h>
void foo(char n)
{
int (*vals)[n] = malloc(sizeof(int[n]));
for (int i = 0; i < n; ++i)
(*vals)[i] = i;
printf("*val is %p\n", *vals);
printf("val is %p\n", vals);
printf("&val is %p\n", &vals);
free(vals);
}
int main()
{
foo(10);
return 0;
}
and this is the output:
*val is 0000018190365d50
val is 0000018190365d50
&val is 0000005d9dbff7b8
note that vals is Array pointer which means that its base type is an array of n integers where the pointer val is created in that stack and points to the whole array, not the first element only and that array is created in the heap, to illustrate, look at the following graph:
so for example if you write:
printf("val is %p\n", vals);
printf("val+1 is %p\n", vals+1);
the output will be :
val is 00000207ef0c5d50
val+1 is 00000207ef0c5d78
note the difference between the 2 is about 40 bytes as val points to the whole array not only one element as in case of int *p = (int*)malloc(n * sizeof(int));
note that when I say it points to the whole array, I also mean it points to the base address of the array.
in case of *Vals, look at the next graph:
*Vals is just an address of the first element of the array which is by the way is same as the base address of the array.
refer to free() manual, they said:
The free() function frees the memory space pointed to by ptr, which
must have been returned by a previous call to malloc(), calloc() or
realloc(). Otherwise, or if free(ptr) has already been called before,
undefined behavior occurs. If ptr is NULL, no operation is performed.
and what does malloc() function return ?
it returns the base address of your reserved space in heap, so writing free(vals); is same as writing free(vals);
This codes uses dynamic VLA.
I think that it may be easier to understand if the code is reformulated with a typedef.
void foo(char n)
{
typedef int T[n];
T *vals = malloc(sizeof(T));
...
free(vals);
}
Now it looks like a tivial use of a single dynamic object.
To access elements of an array first the pointer has to be dereferenced *vals forming an array, which decays to int* pointer suitable for [] operator.
I have issues with my program.
When I launch the program, the console doesn't show the 2 numbers that it should , instead it only shows this:
Process returned -1073741819 (0xC0000005) execution time : 1.759 s
This is my code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
Test(int* Ptr)
{
Ptr=(int*)malloc(8);
if(Ptr==0)
{
printf("malloc error\n");
}
Ptr[0]=155;
Ptr[1]=800;
}
int main()
{
int* m_Ptr=0;
Test(m_Ptr);
printf("%d %d",m_Ptr[0],m_Ptr[1];
return 0;
}
You're main issue is that the pointer you pass into test() is passed by copy. So m_ptr is null when its passed in and its still null when test returns.
You probably want to change your function slightly to something more like:
int* Test()
{
int * Ptr = (int*) malloc(20);
if(Ptr==0)
{
printf("malloc error\n");
}
Ptr[0]=155;
Ptr[1]=800;
return Ptr; // Return the pointer by value
}
And use like (in main):
int* m_Ptr = Test(m_Ptr);
// Now m_Ptr actually points to something...
The argument Ptr in test is a different object in memory from m_Ptr in main - any changes to test::Ptr (such as assigning it the result of malloc) are not reflected in main::m_Ptr. You will either have to pass a pointer or a reference to m_Ptr to test, or test will have to return a pointer value that you assign to m_Ptr:
m_Ptr = Test(); // returns pointer to newly allocated memory.
If this is meant to be C++, then don't use malloc (or calloc, or realloc). Either use a standard container like a vector or set (which automatically grow as new items are added), or use the new operator to manually allocate memory to some kind of smart pointer. Don't use C-style memory management in C++ code; it's labor-intensive, it's unsafe, and it's easy to get things wrong.
With malloc(8) you request 8 bytes.
On a 64bit system sizeof(int) could be 8 bytes.
If so, the line Ptr[1]=800; actually writes to memory beyond the allocated Arena.
Try to change the malloc line to
Ptr=(int*)malloc(sizeof(int)*2)
I came across an old code where I need to allocate memory for an array of matrices. Currently it is done by creating a structure matrix and allocating memory by making an arrray of structures.
Like so.
struct matrix
{
int x[13][13];
};
int main()
{
matrix *push = (matrix*)malloc(sizeof(matrix) * 1000);
//do stuff
free(push);
return 0;
}
But now the question.. Do I really need to do this? I know I am allowed to declare a variable of type int *matrix[13][13];
But I cant seem to figure out a way to allocate memory to this variable.
I tried matrix = (int***)malloc(sizeof(int[13][13])*1000); which results in
E0137 expression must be a modifiable lvalue and honestly in doesnt seem correct either
I know there are many better and creative ways of allocating an array like this, but I am curious
Questions
int *matrix[13][13] what will this kind of variable even mean or represent? Is it a pointer to a 2D matrix or s it an pointer to an array of 2D matrices?
How will I use the above mentioned variable?
How will I allocate memory for the above variable without using any more variables?
Clarifications
From comments it seems int *matrix[13][13] represents a matrix of 13x13 int*
What I am asking is actually, is there a way to have a variable with a dynamically allocated first dimension and static 2nd and 3rd dimensions without using structures typedefs etc
EDIT
As pointed out by felix
what I am looking for is int (*matrix)[13][13] = (int(*)[13][13])malloc(1000*sizeof(matrix));
I have noticed that sometimes beginner programmers are finding typedef-ing the multidimensional matrices which have to be dynamically allocated easier as it reduces the problem to the single star pointer and the sizeof of the defined type and pointer to it is much easier to understand.
#include <stdio.h>
typedef int my13x13matrix[13][13];
int main(void) {
my13x13matrix *mylargematrix = malloc(1000 * sizeof(*mylargematrix));
mylargematrix[999][12][12] = 5;
printf("%d \n", mylargematrix[999][12][12]);
return 0;
}
you can also use the single star pointer arithmetic.
my13x13matrix *anotherpointer = &mylargematrix[10];
(*anotherpointer)[5][5] = 1;
anotherpointer++;
(*anotherpointer)[5][5] = 2;
printf("%d %d\n", mylargematrix[10][5][5], mylargematrix[11][5][5]);
No, you don't want to use
int *matrix[13][13];
That will declare a [13][13] array of int*s.
You need
// pointer to "an array of 13 x 13 ints"
int (*matrix)[13][13];
or simplify it by using a type alias.
typedef int matrix_type[13][13];
matrix_type* matrix_ptr;
You can allocate memory for such a variable using
matrix_type* matrix_ptr = malloc(1000*sizeof(*matrix_ptr));
and assign values to it using
matrix_ptr[0][0][0] = 0;
...
matrix_ptr[999][12][12] = 0;
I'm struggling to learn the C rules of malloc() / free(). Consider the below code, which runs just fine. (On Linux, compiled with GCC.) Specifically, I'm wondering about the arr array. I get that you have to malloc for all the struct elements within the array... but why don't you have to malloc for the array itself?
#include<stdio.h>
#include<stdlib.h>
#define ARR_SIZE 100
typedef struct containerStruct{
int data1;
int data2;
int data3;
// ...etc...
} container;
int main(){
container* arr[ARR_SIZE]; // Don't I have to malloc this?
int i;
for(i=0; i<ARR_SIZE; i++){
arr[i] = (container*) malloc (sizeof(container)); // I get why I have to malloc() here
}
...do stuff...
for(i=0; i<ARR_SIZE; i++){
free(arr[i]); // I get why I have to free() here
}
// Don't I have to free(arr) ?
return 0;
}
I'm guessing that the container* arr[ARR_SIZE]; line tells the compiler all it needs to know to carve out the space in memory for the array, which is why this code works.
But it still doesn't "feel" right, somehow. When I malloc() something, I'm reserving memory space on the heap, right? But my container* arr[ARR_SIZE]; call creates the array on the stack. So... the array of container* porters exists on the stack, and all of those container* pointers point to a container struct on the heap. Is that correct?
Right beneath your declaration of arr, you have the following:
int i;
Which reserves enough space (probably on the "stack") to store an int. Does this "feel" wrong to you as well?
The declaration of arr is no different. The compiler allocates enough space (probably on the "stack") for a ARR_SIZE element array of container *s.
When I malloc() something, I'm reserving memory space on the heap, right?
Don't say that, the heap is an implementation detail. You're dynamically allocating memory. You're also responsible for dynamically freeing it again.
But my container* arr[ARR_SIZE]; call
It's not a call, it's a declaration.
creates the array on the stack.
Don't say that either, the stack is also an implementation detail.
You're declaring a local (here an array of pointers) with automatic scope, and the compiler is responsible for managing its memory and lifetime.
Its lifetime isn't dynamic, because it becomes unreachable as soon as you reach the } at the end of the enclosing block, and so the compiler can handle it for you deterministically.
All local variables behave the same here:
{
int i;
double d[2];
} /* neither i nor d are reachable after here,
so the compiler takes care of releasing any storage */
So... the array of container* pointers exists on the stack,
Consider the simpler declaration container c;. This is a local with automatic scope, and the compiler takes care of (de)allocation as discussed.
Now consider container *p;. This is also a local variable with automatic scope, but the variable is a pointer. You still need to point it at something manually, and if the thing you point it at was returned from malloc, you'll need to free it yourself.
Further consider a simple array container a[2];. Now you have a local array with automatic scope, containing two instances of your container type. Both instances have the same lifetime, it's still managed by the compiler. You can access a[0] and a[1] and pretty much anything else is illegal.
and all of those container* pointers point to a container struct on the heap. Is that correct?
No. Finally consider container* ap[2]. Again we have a local array with automatic scope, containing two pointers. The type of the pointer is pointer-to-container, and the lifetime of the pointers is managed by the compiler. However, the pointers don't point at anything yet, and it'll be your responsibility to decide what to point them at, and figure out what lifetime that pointed-at thing has.
Once you do
ap[i] = malloc(sizeof(*ap[i]));
(you don't need to cast, and it's generally safer to avoid naming the type explicitly, in case you change it later and allocate the wrong size), you've allocated an object which you're responsible for freeing. You've also pointed one of the pointers in your array at this object, but that doesn't somehow change the lifetime of the pointer itself. The array just goes out of scope like usual wherever its pointers point.
You can choose either one of the following options:
int i;
container** arr = malloc(sizeof(container*)*ARR_SIZE);
for (i=0; i<ARR_SIZE; i++)
arr[i] = malloc(sizeof(container));
// do stuff...
for(i=0; i<ARR_SIZE; i++)
free(arr[i]);
free(arr);
int i;
container* arr[ARR_SIZE];
for (i=0; i<ARR_SIZE; i++)
arr[i] = malloc(sizeof(container));
// do stuff...
for(i=0; i<ARR_SIZE; i++)
free(arr[i]);
container arr[ARR_SIZE];
// do stuff...
Since ARR_SIZE is constant, you may as well choose the last option.
Since ARR_SIZE is fixed member of the dynamic array *arr[ARR_SIZE], you no longer have to allocate memory for the whole array, but just the elements within it, as they are flexible in this case.
When you malloc any sort of dynamic array, it is safe to always check the return value of the void* pointer returned from malloc. Additionally, when you free each element, it is even safer to set each member to NULL again, to prevent the pointer from accessing memory again.
Illustrated through this code:
#include <stdio.h>
#include <stdlib.h>
#define ARR_SIZE 100
typedef struct {
int data1;
int data2;
int data3;
// ...etc...
} container_t;
int
main(void) {
container_t *arr[ARR_SIZE];
int i;
for (i = 0; i < ARR_SIZE; i++) {
arr[i] = malloc(sizeof(container_t));
if (arr[i] == NULL) {
printf("Malloc Problem here\n");
exit(EXIT_FAILURE);
}
}
for (i = 0; i < ARR_SIZE; i++) {
if (arr[i]) {
free(arr[i]);
arr[i] = NULL;
}
}
return 0;
}
container* arr[ARR_SIZE]; tells the compiler to allocate an array of ARR_SIZE elements of type container* and compiler allocates the memory accordingly.
In other words, this is similar to saying int x[5] = 0; where compiler allocates enough space for an array of 5 ints. In your case, compiler allocates enough space for ARR_SIZE number of pointers, container* and that is it. Now, it's upto you to make those pointers point to valid memory location. For that, you can either
use memory allocator functions (which allocates memory from heap, as you mentioned)
assign the address of other variables of the same type (does not need allocation from heap, anyway).
So, the bottom line, you don't need to allocate any memory for the array. For each individual array elements, you need to allocate memory using memory allocator functions as you want each elements to point to valid memory.
In this toy code example:
int MAX = 5;
void fillArray(int** someArray, int* blah) {
int i;
for (i=0; i<MAX; i++)
(*someArray)[i] = blah[i]; // segfault happens here
}
int main() {
int someArray[MAX];
int blah[] = {1, 2, 3, 4, 5};
fillArray(&someArray, blah);
return 0;
}
... I want to fill the array someArray, and have the changes persist outside the function.
This is part of a very large homework assignment, and this question addresses the issue without allowing me to copy the solution. I am given a function signature that accepts an int** as a parameter, and I'm supposed to code the logic to fill that array. I was under the impression that dereferencing &someArray within the fillArray() function would give me the required array (a pointer to the first element), and that using bracketed array element access on that array would give me the necessary position that needs to be assigned. However, I cannot figure out why I'm getting a segfault.
Many thanks!
I want to fill the array someArray, and have the changes persist outside the function.
Just pass the array to the function as it decays to a pointer to the first element:
void fillArray(int* someArray, int* blah) {
int i;
for (i=0; i<MAX; i++)
someArray[i] = blah[i];
}
and invoked:
fillArray(someArray, blah);
The changes to the elements will be visible outside of the function.
If the actual code was to allocate an array within fillArray() then an int** would be required:
void fillArray(int** someArray, int* blah) {
int i;
*someArray = malloc(sizeof(int) * MAX);
if (*someArray)
{
for (i=0; i<MAX; i++) /* or memcpy() instead of loop */
(*someArray)[i] = blah[i];
}
}
and invoked:
int* someArray = NULL;
fillArray(&someArray, blah);
free(someArray);
When you create an array, such as int myArray[10][20], a guaranteed contiguous block of memory is allocated from the stack, and normal array arithmetic is used to find any given element in the array.
If you want to allocate that 3D "array" from the heap, you use malloc() and get some memory back. That memory is "dumb". It's just a chunk of memory, which should be thought of as a vector. None of the navigational logic attendant with an array comes with that, which means you must find another way to navigate your desired 3D array.
Since your call to malloc() returns a pointer, the first variable you need is a pointer to hold the vector of int* s you're going to need to hold some actual integer data IE:
int *pArray;
...but this still isn't the storage you want to store integers. What you have is an array of pointers, currently pointing to nothing. To get storage for your data, you need to call malloc() 10 times, with each malloc() allocating space for 20 integers on each call, whose return pointers will be stored in the *pArray vector of pointers. This means that
int *pArray
needs to be changed to
int **pArray
to correctly indicate that it is a pointer to the base of a vector of pointers.
The first dereferencing, *pArray[i], lands you somewhere in an array of int pointers, and the 2nd dereferencing, *p[i][j], lands you somewhere inside an array of ints, pointed to by an int pointer in pArray[i].
IE: you have a cloud of integer vectors scattered all over the heap, pointed to by an array of pointers keeping track of their locations. Not at all similar to Array[10][20] allocated statically from the stack, which is all contiguous storage, and doesn't have a single pointer in it anywhere.
As others have eluded to, the pointer-based heap method doesn't seem to have a lot going for it at first glance, but turns out to be massively superior.
1st, and foremost, you can free() or realloc() to resize heap memory whenever you want, and it doesn't go out of scope when the function returns. More importantly, experienced C coders arrange their functions to operate on vectors where possible, where 1 level of indirection is removed in the function call. Finally, for large arrays, relative to available memory, and especially on large, shared machines, the large chunks of contiguous memory are often not available, and are not friendly to other programs that need memory to operate. Code with large static arrays, allocated on the stack, are maintenance nightmares.
Here you can see that the table is just a shell collecting vector pointers returned from vector operations, where everything interesting happens at the vector level, or element level. In this particular case, the vector code in VecRand() is calloc()ing it's own storage and returning calloc()'s return pointer to TblRand(), but TblRand has the flexibility to allocate VecRand()'s storage as well, just by replacing the NULL argument to VecRand() with a call to calloc()
/*-------------------------------------------------------------------------------------*/
dbl **TblRand(dbl **TblPtr, int rows, int cols)
{
int i=0;
if ( NULL == TblPtr ){
if (NULL == (TblPtr=(dbl **)calloc(rows, sizeof(dbl*))))
printf("\nCalloc for pointer array in TblRand failed");
}
for (; i!=rows; i++){
TblPtr[i] = VecRand(NULL, cols);
}
return TblPtr;
}
/*-------------------------------------------------------------------------------------*/
dbl *VecRand(dbl *VecPtr, int cols)
{
if ( NULL == VecPtr ){
if (NULL == (VecPtr=(dbl *)calloc(cols, sizeof(dbl))))
printf("\nCalloc for random number vector in VecRand failed");
}
Randx = GenRand(VecPtr, cols, Randx);
return VecPtr;
}
/*--------------------------------------------------------------------------------------*/
static long GenRand(dbl *VecPtr, int cols, long RandSeed)
{
dbl r=0, Denom=2147483647.0;
while ( cols-- )
{
RandSeed= (314159269 * RandSeed) & 0x7FFFFFFF;
r = sqrt(-2.0 * log((dbl)(RandSeed/Denom)));
RandSeed= (314159269 * RandSeed) & 0x7FFFFFFF;
*VecPtr = r * sin(TWOPI * (dbl)(RandSeed/Denom));
VecPtr++;
}
return RandSeed;
}
There is no "array/pointer" equivalence, and arrays and pointers are very different. Never confuse them. someArray is an array. &someArray is a pointer to an array, and has type int (*)[MAX]. The function takes a pointer to a pointer, i.e. int **, which needs to point to a pointer variable somewhere in memory. There is no pointer variable anywhere in your code. What could it possibly point to?
An array value can implicitly degrade into a pointer rvalue for its first element in certain expressions. Something that requires an lvalue like taking the address (&) obviously does not work this way. Here are some differences between array types and pointer types:
Array types cannot be assigned or passed. Pointer types can
Pointer to array and pointer to pointer are different types
Array of arrays and array of pointers are different types
The sizeof of an array type is the length times the size of the component type; the sizeof of a pointer is just the size of a
pointer