I've always programmed in Java, which is probably why I'm so confused about this:
In Java I declare a pointer:
int[] array
and initialize it or assign it some memory:
int[] array = {0,1,0}
int[] array = new int[3]
Now, in C, it's all so confusing. At first I thought it was as easy as declaring it:
int array[]
and initializing it or assigning it some memory:
int array[] = {0,1,0}
int array[] = malloc(3*sizeof(int))
int array[] = calloc(3,sizeof(int))
Unless I'm wrong, all of the above is equivalent Java-C, right?
Then, today I met a code in which I found the following:
pthread_t tid[MAX_OPS];
and some lines below, without any kind of initialization...
pthread_create(&tid[0],NULL,mou_usuari,(void *) 0);
Surprisingly (at least to me), the code works! At least in Java, that would return a nice "NullPointerException"!
So, in order:
Am I correct with all of the Java-C "translations"?
Why does that code work?
Is there any difference between using malloc(n*sizeof(int)) and calloc(n,sizeof(int))?
Thanks in advance
You can't assign memory to an array. An array has a fixed size, for the whole of its lifespan. An array can never be null. An array is not a pointer.
malloc returns the address to a memory block that is reserved for the program. You can't "assign" that (being the memory block) to an array, but you can store the address of this memory block in a pointer: luckily, array subscription is defined through pointers - so you can "use pointers like arrays", e.g.
int *ptr = malloc(5 * sizeof *ptr);
ptr[2] = 5; // access the third element "of ptr"
free(ptr); // always free at the end
When you declare an array without a size (i.e. array[]), it simply means the size of the array is determined from the initializer list. That is
int array[] = {1, 2, 3, 4, 5}; // is equal to
int array[5] = {1, 2, 3, 4, 5};
Trying to declare an array without a size and without an initializer is an error.
The code pthread_t tid[MAX_OPS]; declares an array named tid of type pthread_t and of size MAX_OPS.
If the array has automatic storage (i.e. declaration is inside a function and not static, not global), then each of the arrays elements has indeterminate value (and it would cause undefined behavior trying to read such value). Luckily, all that the function call does is that it takes the address of the first element of the array as the first parameter, and probably initializes it (the element) inside the function.
The difference of calloc and malloc is that the memory block that calloc returns is initialized to zero. That is;
int *ptr = calloc(5, sizeof *ptr);
// is somewhat equal to
int *ptr = malloc(5 * sizeof *ptr);
memset(ptr, 0, 5 * sizeof *ptr);
The difference between
int *ptr = malloc(5 * sizeof *ptr);
// and
int array[5];
is that array has automatic storage, (is stored on stack), and is "released" after it goes out of scope. ptr, however, (is stored on heap), is dynamically allocated and must be freed by the programmer.
You are missing three very basic and tighten (and misleading!) C topics:
the difference between array and pointers
the difference between static and dynamic allocation
the difference from declaring variables on the stack or on the heap
If you write int array[] = malloc(3*sizeof(int)); you would get a compilation error (something like 'identifier' : array initialization needs curly braces).
This means that declaring an array allows only static initialization:
int array[] = {1,2,3}; that reserves 3 contiguous integers on the stack;
int array[3] = {1,2,3}; which is the same as the previous one;
int array[3]; that still reserves 3 contiguous integers on the stack, but does not initialize them (the content will be random garbage)
int array[4] = {1,2,3}; when the initializer list doesn't initialize all the elements, the rest are set to 0 (C99 §6.7.8/19): in this case you'll get 1,2,3,0
Note that in all these cases you are not allocating new memory, you are just using the memory already committed to the stack. You would run in a problem only if the stack is full (guess it, it would be a stack overflow). For this reason declaring int array[]; would be wrong and meaningless.
To use malloc you have to declare a pointer: int* array.
When you write int* array = malloc(3*sizeof(int)); you are actually doing three operations:
int* array tells the compiler to reserve a pointer on the stack (an integer variable that contains a memory address)
malloc(3*sizeof(int)) allocates on the heap 3 contiguous integers and returns the address of the first one
= assigns copies that return value (the address of the first integer you have allocated) to your pointer variable
So, to come back to your question:
pthread_t tid[MAX_OPS];
is an array on the stack, so it doesn't need to be allocated (if MAX_OPS is, say, 16 then on the stack will be reserved the number of contiguous bytes needed to fit 16 pthread_t). The content of this memory will be garbage (stack variables are not initialized to zero), but pthread_create returns a value in its first parameter (a pointer to a pthread_t variable) and disregards any previous content, so the code is just fine.
C offers static memory allocation as well as dynamic- you can allocate arrays off the stack or in executable memory (managed by the compiler). This is just the same as how in Java, you can allocate an int on the stack or an Integer on the heap. Arrays in C are just like any other stack variable- they go out of scope, etc. In C99 they can also have a variable size, although they cannot be resized.
The main difference between {} and malloc/calloc is that {} arrays are statically allocated (don't need freeing) and automatically initialized for you, whereas malloc/calloc arrays must be freed explicitly and you have to initialize them explicitly. But of course, malloc/calloc arrays don't go out of scope and you can (sometimes) realloc() them.
2 - This array declaration is static :
pthread_t tid[MAX_OPS];
We don't need to allocate memory block, instead of dynamic allocation :
pthread_t *tid = (pthread_t *)malloc( MAX_OPS * sizeof(pthread_t) );
Don't forget to free the memory :
free(tid);
3 - The difference between malloc and calloc is calloc allocate a block of memory for an array and initializes all its bits at 0.
I find it helpful when you are programming in C (as opposed to C++) to indicate *array explicitly, to remember that there is a pointer that can be moved around. So I would like to start by rephrasing your example as:
int array[] = {0,1,2};
int *array = malloc(3*sizeof(int));
int *array = calloc(3,sizeof(int));
The first makes it clear that there is something called array which is pointing to a block of memory that contains a 0, 1 and 2. array can't be moved elesewhere.
Your next code:
pthread_t tid[MAX_OPS];
Does in fact cause an array with sizeof(pthread_t) * MAX_OPS to be allocated. But it does not allocate a pointer called *tid. There is an address of the base of the array, but you can't move it elsewhere.
The ptherad_t type is actually a cover for a pointer. So tid above is actually an array of pointers. And they are all statically allocated but they are not initialized.
The pthread_create takes the location at the beginning of the array (&tid[0]), which is a pointer, and allocates a block of memory to hold the pthread data structure. The pointer is set to point to the new data structure and the data structure is allocated.
Your last question --- the difference between malloc(n*sizeof(int)) and calloc(n,sizeof(int)) is that the later initializes each byte to 0, while the first does not.
Related
I have a very basic question on memory allocation in C.
If I write:
int* test;
test = malloc(5 * sizeof(int));
test[0] = 1;
test[1] = 2;
test[2] = 3;
test[3] = 4;
test[4] = 5;
test = realloc(test, 6 * sizeof(int));
I am able to use realloc. If I define test as:
int test[5] = {1,2,3,4,5};
I am not able call realloc on it.
What is the lower level difference between these statements?
Can I somehow realloc on test[5]?
How do I free test[5]?
I am not sure where to look for an answer, if you could link a resource, I would be thankful.
You cannot use realloc() to int test[5] because this test is not a pointer allocated via memory management functions (like malloc()) nor NULL.
Quote from N1570 7.22.3.5 The realloc function:
If ptr is a null pointer, the realloc function behaves like the malloc function for the
specified size. Otherwise, if ptr does not match a pointer earlier returned by a memory
management function, or if the space has been deallocated by a call to the free or
realloc function, the behavior is undefined. If memory for the new object cannot be
allocated, the old object is not deallocated and its value is unchanged.
You cannot do re-allocation of int test[5]. (At least there are no standard way, but I cannot say there are no extended compiler that supports that).
To free int test[5], exit from the block in which that is declared if it is a local variable. Such variable has an automatic storage duration and it is freed on exiting from the block. If it is a global (or static local) variable, exit the process and the OS will free the memory used by the process.
You cannot change the size because the type of test in int test[5] = {1,2,3,4,5}; is int[5]. Number 5 is a part of its type and objects in C cannot change type after creation.
In int* test;, the test is a pointer and it can point to a memory region of an arbitrary number of consecutive ints.
I'm very new to C and I have trouble understanding array pointers. I'm trying to make a array bigger,I copy all of its element to new bigger array but I can't make original variable to point the new array. I'm use to C# where you can do
double[] array1 = new double[5];
double[] array2 = new double[10];
array1 = array2;
I did something similar using int array
int array1 [5];
int array2 [10];
*array1 = &array2;
and it compile but crash the program. Same lines but double or char[] (I was told to use char[] instead of sting in C) do not even compile
[Error] incompatible types when assigning to type 'double' from type 'double (*)[(sizetype)(newsize)]'
The results I found on the topic told me to use double* array1 for variable type but this change the interactions with that variable.
If someone can explain the concept to me or at least tell me what to search for that will be huge help.
I do know the basics of pointers!
There are a few things you need to know about arrays (and pointers):
The first is that arrays and pointers are two different things;
The second is that an array can decay to a pointer to its first element. So if you use array1 (from your example) when a pointer is expected, that's the same as doing &array1[0]. The type of such a pointer is a pointer to a single element type (so for array1 the type will be int *);
The third thing is that for any array of pointer a and index i, the expression a[i] is exactly equal to *(a + i). That means *array1 (again from your example) is the same as array1[0] (*array1 is equal to *(array1 + 0) which is equal to array1[0]);
An array will have a fixed size. Once defined the size of an array can't change;
Lastly when you get a pointer to an array (as in &array2) then you get a pointer to the actual array, not to one of its elements. The type of e.g. &array2 is int (*)[10].
Now we can puzzle together the statement
*array1 = &array2;
If we do the array-indexing replacement for *array1 then we get
array[0] = &array2;
And here we can see a big problem: The type of a single element of array1 is a plain int. So what the assignment is trying to do is to assign a pointer to an array (of type int (*)[10]) to a single int.
If you want to copy all the elements from one array to another, then use the memcpy function. You're not allowed to assign between arrays.
But beware of the different sizes for array1 and array2. If you go out of bounds of an array (or other allocated memory) you will have undefined behavior.
In C there is no way to make an array variable "reference" a different variable. If you need to use "references" they can be emulated using pointers:
int *pointer1 = array1; // array1 here will decay to &array[0]
int *pointer2 = array2; // Same here for array2
With the above definition pointer1 is (in a way) "referencing" array1. You can now use pointer1 and array1 almost interchangeably.
One major difference between using pointers and arrays is how their sizes are calculated: When you do sizeof on an array you get the size (in bytes) of the whole array. Assuming 32-bit int (the most common) then sizeof array1 will return 5 * 4 (or 20) as the size. If you get the size of a pointer, you get the size of the pointer itself, not what it might point to. So sizeof pointer1 will return either 4 or 8 (depending on if you're in a 32-bit or 64-bit system).
Going back to references, we can now change where pointer1 is pointing:
pointer1 = pointer2; // Assuming pointer2 is unchanged, equivalent to pointer1 = array2
Now pointer1 and pointer2 are pointing to the same array, array2.
In C# you can overload the = to copy the arrays. In C it is just simple assignment.
In C arrays decays to pointers for the sake of simplicity. In C *(array + N) == array[N] and *array == array[0]
int array1 [5]; it is not the array of pointers only integers so *array1 = &array2; assigns array[0] with address of the first element of the the array2 converted to signed integer which generally doesn't make too much sense and it does not copy array2 to array
To copy array you need to use memcpy or the loop to copy the element. You need to make sure that the destination array is large enough to accommodate the second array. C will not change the destination array size.
The assignments that your are doing is wrong. Basically a pointer points to a block of memory. from your code I can understand that array1 = array2; and *array1 = &array2; is wrong.
Syntax in C is something like this data-type* pointer-variable = (data-type*)malloc(no. of bytes you want);
See consider you want 10 block of memory of type int
int *p = (int *)malloc(10 * sizeof(int))
sizeof(int) return 4 bytes.
Now p points to 10 * 4 = 40 bytes of memory, I multiplied by 4 because int is usually of 4 bytes and double is of 8 bytes and so on.
Follow this link to understand C - Data Types
Now regarding changing pointers refer below example and read the comments
int *q = NULL // declare a pointer of same type as the block of memory it is going to point
q = p; //now q and p point same memory of 40 bytes, means value at q[0] is equal to p[0]
When you have an integer pointer and you increment it by p++ it will point to next memory location p[1], pointer will be exactly incremented by 4 bytes as int size is 4 bytes and for double it will be 8 bytes, for char it will be 1 byte and so on.
Now if you want to increase the size of dynamically allocated memory you can use realloc please follow this link to understand more.
Dynamic Memory Allocation in C
int *p = NULL;
// Dynamically allocate memory using malloc()
p = (int*)malloc(no. of bytes, sizeof(int));
// Dynamically re-allocate memory using realloc()
p = realloc(p, (no. of bytes) * sizeof(int));
// Avoid memory leaks
free(p);
Syntax in C++ is something like this data-type* pointer-variable = new data-type[size];
See consider you want 10 block of memory of type int
int *p = new int[10]
Just use new operator to allocate block of memory and use delete to free allocated memory to avoid memory leaks.follow this link
new and delete operators in C++ for dynamic memory
Or If you are looking for containers where you don't know how much memory should be allocated the use standard template library vector, it helps creating dynamic arrays.follow this link
Vector in C++ STL
This question already has answers here:
Is an array name a pointer?
(8 answers)
Closed 4 years ago.
So, in C, this perfectly works:
int myArray[] = {1, 2, 3};
why does the following give me a runtime error when accessing an element?
int * myArray2 = {1, 2, 3};
myArray2[0];
when myArray2[0] basically means *myArray2, which does also not work?
I think that the fundamental difference is that declaring an array implicitly allocates memory, while declaring a pointer does not.
int myArray[3]; declares an array and allocates enough memory for 3 int values.
int myArray[] = {1,2,3}; is a little syntactic sugar that lets the size of the array be determined by the initialization values. The end result, in terms of memory allocation, is the same as the previous example.
int *myArray; declares a pointer to an int value. It does not allocate any memory for the storage of the int value.
int *myArray = {1,2,3}; is not supported syntax as far as I know. I would expect you would get a compiler error for this. (But I haven't done actual C coding in years.) Even if the compiler lets it through, the assignment fails because there is no memory allocated to store the values.
While you can deference a pointer variable using array syntax, this will only work if you have allocated memory and assigned its address to the pointer.
Pointer and Array are different. One difference between them is the subject of your question. When you define an array with the specified size, you have enough memory to initialize it.
However, in the pointer, you should allocate the memory to initialize it. Hence, you should first allocate the memory using a function like malloc and point the pointer to the allocated memory. Therefore, the problem with the second code is you want to access the part of the memory which is not allocated.
You can correct it likes the following:
int *myarray2 = malloc(3*sizeof(int));
myarray2[0] = 1;
myarray2[1] = 2;
myarray2[2] = 3;
I created an array of 10 elements in C inside of main and declared values for only some of the elements. When printing out the array I noticed that one of the elements, which was left untouched, was not initialized to zero. Instead, it was initialized to a different large value every time (i.e. 1491389216). I then commented out all of my code and just left the array as I initially declared it.
When running the code, the first 8 elements of the array were initialized to zero, the 9th element in the array was being initialized to a large value (like 1491389216) which changed every time, and the last element was consistently being initialized to the same non-zero number.
Does anyone have any idea why this is happening?
Local (automatic) arrays are not initialized unless you explicitly initialize them. Otherwise they contain whatever random data already occupies the memory.
If you want to zero out all of the elements when declaring the array, you can do this:
int arr[10] = {0};
Or:
int arr[10] = {};
Depending on your compiler (GCC allows this, unless you specify -pedantic).
Or, just use memset() instead:
int arr[10];
memset(arr, 0, sizeof(arr));
Similarly, memory allocated by malloc() — or extended by realloc() — is not initialized; use calloc() to zero-initialize such data:
int *arr = (int*) calloc(10, sizeof(int));
...
free(arr);
I am new to C++. I am having trouble differentiating between initializing an array and mallocing memory. To me, they seem to accomplish the same purpose.
Specifically, I can initialize an array via int myArray[] = {1, 2, 3};. I can also use malloc to obtain memory and assign it to a void pointer. Later, I free this memory.
What is the difference between these two methods? Does a computer store the data in the same places and in the same ways?
In C++ there are two different ways you can allocate memory. The first way allocates memory on the stack.
int arr[] = {1,2,3};
int arr[3];
Both of these lines of code create an array of size 3 on the stack. The only difference is the first line also initializes the values in the array.
The second way you can allocate memory is on the heap. The amount of memory available on the heap is usually much larger than is available on the stack. The new and malloc operations allocate memory on the heap.
int* arr = (int*) malloc(100*sizeof(int));
int* arr = new int[100];
Both of these lines of code create an array of size 100 on the heap. Now here's the difference between the two. In C++ you should always use new because it ensures that the constructors for each element in your array are called. It is also much more type safe, unlike malloc which isn't type safe at all since it just returns a void* to a chunk of bytes that can be interpreted anyway you'd please.
Now if you're dynamically allocating memory, meaning you don't know the size of the array until runtime, you should always allocate it on the heap using new/malloc.
Last thing to note is how you free your memory, using delete/free.
free(arr); //arr was allocated with malloc
delete[] arr; //arr was allocated with new
If you allocated memory with new it must be freed with delete. You can't mix and match new/malloc with delete/free. Lastly delete[] frees an array of objects. If you only allocated a single object then you just use delete.
Object* myobj = new Object;
delete myobj;
In my opinion, this question does not belong to here. But I will answer it. You can do that with:
int* myArray = (int *) malloc(3 * sizeof(int));
This means that you are creating memory location with memory size 3 * sizeof(int) [i.e. the size of the integer data type in C], and you re returning an int pointer to this memory location. [i.e. a pointer that points to the beginning of it, and deal with it as it if contains integers]. These memory slots are converted to int * (using (int *)), and called myArray. myArray is an int array (and an int pointer). Because arrays are actually pointers in C. Then you do:
for (int i = 0; i < 3; i++)
myArray[i] = i + 1;
There could be some issues in malloc. Therefore, after the initialization always check if myArray == NULL. If this is case, fix the error, and dont initialize the array with $\{1,2,3\}$. Otherwise, you will get a segmentation fault.
I wish I am not vague to you. But since you are using C++, I would suggest you use the new operator instead. you would do:
int myArray[] = new int[3];