Initializing array (pointer) with values [duplicate] - c

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;

Related

How do array pointers work in C and how to change pointers

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

Why does char* create a string?

I'm confused as to why I can create a string by using just char*. Isn't a char* just a pointer to a single char? What makes me suddenly allowed to treat this thing as a string? Can I do this with other objects? What about:
int* arr;
Do I now have an array of ints? Is it dynamically sized? Can I just start calling
arr[0] and arr[1]
and expect it to work?
I've been googling for quite awhile now, and can't find any clear answer to this question.
This is one part of C I've always just accepted as the way it works...no more.
Pointers point to things. int *arr; currently does not point anywhere. You cannot treat it as pointing to anything (array or otherwise).
You can point it at something. If you point it at a single int, you can treat it as pointing to a single int. If you point it at an element of an array of ints, you can treat it as pointing to an element of an array.
char behaves the same as int (or any other object type) in this respect. You can only treat a char * as pointing to a string if you first point that char * to a string.
Isn't a char* just a pointer to a single char?
It is a pointer to a memory location that should hold a char. It can be a single allocated char, or an array of several char's.
What makes me suddenly allowed to treat this thing as a string?
When the char* pointer points to a memory location where several chars[] are allocated one after another (an array), then you can access them with an array index [idx]. But you have to either:
A. Use a statically allocated array in code:
char myArray[5];
B. or Dynamic allocation (malloc() in C language):
int chars_in_my_array = 10;
char* myArray = (char*)malloc( sizeof(char) * chars_in_my_array );
Can I do this with other objects? What about: int* arr; Do I now have an array of ints?
no you don't:
int* p; //'p' is a *pointer* to an int
int arr[10]; //'arr' is an array of 10 integers in memory.
You can set 'p' to point to the first element in 'arr' by doing this:
p = &arr[0]; //'p' points to the address of the first item in arr[]
Is it dynamically sized?
No. That's something you'd see in a higher-level construct like 'std::string' in C++, or 'String' in Java. In C, memory is managed manually (or you use existing library functions to do this for you. see the standard header file 'string.h')
Can I just start calling arr[0] and arr[1] and expect it to work?
Not unless you do this:
int arr[5];
arr[0] = 100; arr[1] = 200;
...Because you statically allocate an array of five integers. Then you can access them with an array subscript.
However you can NOT do this:
int* p;
p[0] = 100; p[1] = 200; // NO!!
Because 'p' is just a variable that contains a memory address to an integer. It doesn't actually allocate any memory unless you explicitly allocate memory for it. You can do this though:
int* p;
int arr[10];
p = &arr[0];
p[0] = 100; p[1] = 200; // This is OK
This works because 'p' now points to memory that has been (statically) allocated for an array. So we can access the array through the pointer 'p'.
You can also dynamically allocate the array:
int* p;
p = (int*)malloc( sizeof(int) * 10 );
if( p != NULL ) {
p[0] = 100;
p[1] = 200;
}
Here we allocate memory for 10 integers and 'p' points to the first item. Now we can use 'p' as an array. But only for 10 items maximum!
I've been googling for quite awhile now, and can't find any clear
answer to this question. This is one part of C I've always just
accepted as the way it works...no more.
Really? Try googling 'arrays in c', 'memory allocation in C', 'static vs dynamic allocation C', and functions such as malloc() and free(). There's a plethora of information available, but hope this helps for starters :)

Does "a[0]" mean something more than just "a"? [duplicate]

This question already has answers here:
What happens if I define a 0-size array in C/C++?
(8 answers)
Closed 8 years ago.
Me and a friend of mine are arguing about that so we thought
here we can get an appropriate answer, with the corresponding explanation.
int a[0];
is a[0] an array and does it have any advantages?
(I didn't only want to know what happened if I defined a and a[0] but also want to know the advantages and how it was more than just the variable.)
As a standalone stack variable, it is not useful. However, as the last member of a struct, it can be used as a variable length array and doing this used to be a common technique. For example:
struct foo {
int a[0];
};
struct foo* bar = malloc( sizeof *bar + 10 * sizeof *bar->a );
/* now you can (possibly) use bar->a as an array of 10 ints */
Note that this is a non-standard, non-portable hack and is certainly not good practice in new code.
YES, they are different according to their functionality.
Lets first get into their memory address.
int a[0];
printf("%p / %p", &a[0], &a);
As you can test a[0] uses the same address as a.
That means they are the same, but that doesn't mean their behaviour is the same.
That because &a aways points to a[0] which is the only one memory area allocated here.
However.. despite the logics, a[0] IS considered array.
Many people say that an array needs to have more then 1 memory block used, but thats wrong.
And that is because of the index operator [] which is what actually makes something an array. (systematic arrangement of objects)
Even if the object is one as it appears in here a[0] it is accepted as an array by the compiller and the debug. And you will have to
initialize the array in case you want to assign value INTO it.
Valid:
int a[] = {1};
Valid:
int a[0] = {1};
Invalid:
int a[0] = 1;
On top of that, converting a pointer to the array is valid as follows:
int a[0];
int* p;
p = a;
However you can't just set p to point into a one block of memory, it is reserved for the datatype. At the end we have an integer that points to itself.
The conclusion is that the compiler/debug and you by yourself can threat it like an array, but you can't use it.
(Or at least to expect propper result)
All that means that the difference between a an a[0] is the ability of a to point to its address.

How is initializing an array different from mallocing memory?

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];

I'm very confused about malloc() and calloc() on C

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.

Resources