These two are different programs for declaring a 2D array
1)i think they are same because both are 2D array?
2)can we access both using a[i][j] and p[i][j]?
3)Why *a or a are same and p or *p are different
#include<stdio.h>
#include<stdlib.h>
int main(){
int a[100][100];
printf("%d\n",a);
printf("%d\n",*a);
int **p=malloc(sizeof(int*)*100);
for(int i=0;i<100;i++){
p[i]=malloc(sizeof(int)*100);
}
printf("%d",p);
printf("%d",*p);
}
the big difference is that in case with a[100][100] the compiler knows the full size of the array and allocates a contiguous memory region on a stack (as in your case) or in static area. When accessing an array element, the compiler is free to calculate its address based on the array dimensions and use a single reference to access it. like this
[0,0][0,1][0,2]...[0,99][1,0][1,1][1,2]...[99,0]...[99,99]
+-------0------...-----+----- 1 -------...+----- 99 -----+
In case of the dynamic allocation, which you used, the memory is allocated contiguously only for a single dimension of the array. So, you allocate 100 pointers, every one of each points to a single dimensional array of integers. Those arrays can be placed at arbitrary memory locations. As a result, the compiler has to do at least 2 references in this case, use first index to get a pointer to the second array, than use the second index to get the element in the second array.
pointers[index0] : [0][1][2]..[99]
/ | \
/ | |
V V V
[0] [0] [0]
[1] [1] [1]
... ... ...
some addition about a and *a. In 'c' when the name of the array is used in a pointer like context, it is interpreted as an address of the array. So, in printf a points to the beginning of the two-dimensional array. *a for same reason is supposed to provide you an address of the first column. Which in this case is the same as the start or the array. **a will point you to the very first array element a[0][0]. And by the way, it is better to use %p there instead of %d for pointers.
You can see that for the dynamic array p gives you the address of the array of pointers, whether *p gives you the value of its first element p[0] which by itself is a pointer to the column. The addresses are definitely different.
But in both cases you can use a[i][j] and p[i][j] to access array elements.
They are not the same. The first (int a[100][100]) is a single variable that is a compound object. The other (int **p) is a collection of arrays that you are using as a data structure for matrices.
If you want to have an actual 2D array in dynamic storage, this is how you do it:
#include <stdlib.h>
int main()
{
int (*m)[100][100];
m = malloc(sizeof *m);
for (int i = 0; i < 100; i++)
for (int j = 0; j < 100; j++)
(*m)[i][j] = 0;
}
Of course, the syntax is a bit weird, and you would rather have a dynamic matrix with variadic number of columns and rows, which is why you would prefer to declare a matrix pointed by int **p.
The reason why a and *a give the same output is because both decay to a pointer to the first element of a, which is a[0][0]. On the other hand, p is a pointer itself, and *p is the contents of the variable pointed by p. They are just as different as they would be if you did this:
int d = 0;
int *p = &d;
printf("%p\n", p);
printf("%d\n", *p);
Now back to your int **p.
Yes, you can access both int a[][100] and int **p with double indexing. However, there is a fundamental difference in the way the compiler treats a[i][j] and p[i][j].
In a[i][j], each a[i] is an array of 100 integer objects. So in order to access the i-th element, and then the j-th element, the compiler has to acess the i*100+j-th element from a[0][0]. This access can be performed in a single step with some index arithmetic.
In v[i][j], each v[i] is a pointer which may point to objects far from each other in memory. In order to acess the element v[i][j], the compiler must first follow p to the array *p, then find the i-th element in this array, which is a pointer to the array p[i]. And then with some pointer arithmetic it will find the j-th element of this array.
a is the address of the array in memory, its value depends on how your compiler and operating system layout memory. *a is the value in memory at that location, again depending on your operating system this is either random or set to some pre-determined value. Similarly for p and *p
For ease of debugging most operating systems set memory to some deliberate fixed value. Unix typically sets malloc() memory to zero.
Windows has a range of default contents depending on how the memory was allocated see: When and why will an OS initialise memory to 0xCD, 0xDD, etc. on malloc/free/new/delete?
Related
My teacher told me that int **array is not a 2D array, it is just a pointer to a pointer to an integer.
Now, in one of my projects I have to dynamically allocate a 2D array of structs, and this is how it is done:
struct cell **array2d = (struct x **)calloc(rows, sizeof(struct x *));
for (int i = 0; i < columns; i++) {
array2d[i] = (struct x *)calloc(j, sizeof(struct x));
}
But here we return a pointer to a pointer to the struct, so how is this a 2D array?
Before using dynamic allocation, I had a statically allocated array of the form:
array2d[][]
Now that I replaced it by dynamic allocation, I also replaced array2d[][] by **array2d.
Every function that takes array2d[i][j] als argument now returns an error saying the types don't match.
Could someone explain me what is happening here? What is the difference between **array and array[m][n] and why is the compiler complaining?
They're thoroughly different things.
An array is a sequence of values of the same type stored one after another in memory.
In C, an array is more or less interchangeable with a pointer to its first element — a[0] is *a,
a[1] is *(a+1), etc. — at least when we're talking about one-dimensional arrays.
But now consider:
int a[3][3];
in this case, a contains nine elements, contiguous in memory. a[0][0] through a[0][2], then a[1][0] immediately after, up until a[2][2].
If you pass a to a function, it would fit into a parameter type of int * or int[3][3] or int [][3] (knowing the "stride" of the second dimension is absolutely necessary to doing the math to look up a given element).
On the other hand:
int *b[3];
b[0] = malloc(...);
b[1] = malloc(...);
b[2] = malloc(...);
in this case, b is an array of 3 elements, each of which is a pointer to an array of 3 elements. You still access it like b[0]0] or b[1][2], but something completely different is happening under the hood. The elements aren't all stored contiguously in memory, and *b isn't any of them, it's a pointer. If we were to pass b to a function, we would receive it with a parameter of type int ** or int *[]. Knowing the length of each row in advance isn't necessary, and in fact each row could have a different length from the others. Some of the rows could even be null pointers, with no storage behind them for integers.
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
If I have:
int A[10][20];
printf("%p",A[3]);
it will print the address of A[3][0].
However, I'd like to know if this one dimensional array A[3] containing pointers really exists, or it is calculated in some way.
The way you have defined A means that the compiler will allocate for it a contiguous block of memory large enough to hold 10 x 20 (200) integers; see here (scroll down to "Multidimesional arrays"). As I'm sure you realize, if you were to do printf("%p", A); you would see the address of the beginning of that allocated block.
Now, when the compiler sees the expression A[3], it will add what it calculates as the necessary amount of "integer sizes" to the base address (that of A, or A[0][0]); in this case, it will add "3" (the index specified) multiplied by the combined size of all the other dimensions (in this case, there's only one, which is 20).
So, in your case, there is no actual array of pointers; just a memory block that the compiler can interpret according to how you described any part(s) of it.
However, in a more versatile approach, one can actually define a 2D array in terms of an actual array of pointers, like so:
int **A;
A = malloc(10 * sizeof(int*));
for (int n = 0; n < 10; ++n) A[n] = malloc(20 * sizeof(int));
In this case, using printf("%p",A[3]); would still be valid, but it would give a very different offset value from printf("%p",A); or printf("%p",A[0]);.
It's also, perhaps, worth noting that, even though these two different declarations for A can both resolve an individual element through an expression like A[i][j] (but the compiler would evaluate the addresses differently), there is here scope for major confusion! When, for example, passing such an array to a function: if the function expects data allocated in the second form, and you give it an array defined in the first form (and vice versa), you're gonna get major undefined behaviour .
yes there is a way to calculate the position:
for A[i][j]
the position of the memory block will be
pos = A + i*(number_of_columns_in_each_row) + j
here A is the pointer to the first element of the array
However, I'd like to know if this one dimensional array A containing pointers really exists, or it is calculated in some way.
The way you defined the array A :
int A[10][20];
does not contain any pointers as elements of the array. it contains only integer elements.
if you want to make an array of pointers, which should be assigned to int-variables is defined like that:
int *A[10][20];
You also can set a pointer to the start of the array, which means element [0] [0]
by using:
int *pointer;
int *A[10][20];
pointer = &A;
You also be able to set the pointer slightly forwards according to each element by increase the pointer.
pointer++;
I've been learning C for about 2 months, still a novice:(
I know there are other similar questions on this site. I've read them, but still couldn't really understand, so here I am. Below is my code:
//naming my structure as ball
typedef struct ball_room {
int enter;
int exit;
} ball;
//I've omitted some irrelevant details for brevity
int i, n, max;
scanf("%d", &n);
ball person[n];
.../*assign values to ball.enter and ball.exit with user input*/
max = 1;
for (i = 0; i < n; i++)
if (ball_room(person, person[i].enter, n) > max)
max = ball_room(person, person[i].enter, n);
printf("%d\n", max);
return 0;
}
and below is my function receiving the array:
//This function returns the number of people in the ballroom
//when b[j](person[j] in "main") enters
int ball_room(ball *b, int i, int n)
{
int people = 0, j;
for (j = 0; j < n; j++)
if (b[j].enter <= i && b[j].exit > i)
people++;
return people;
}
my question is that why is it b[j].enter instead of b[j]->enter, which my compiler wouldn't accept?
In my limited experience, when manipulating structure itself (the object), I use . to go inside the structure, and when it's a pointer (the address), I use -> (hope this is correct.)
And in this case, I pass the array to function using ball *b, which represent the address of person[0], so I can access the whole array. But shouldn't ball *b be in the form of a pointer and therefore I should use -> to access its content? It's just an address that I pass to the function.
This is my first time doing something with an array of structures, please help me get this clear, thank you!
Given ball *b, b[j] is an element from the elements that b points to. Thus b[j] is not a pointer; it is a struct. Since it is a struct, you use . to refer to members in it.
The definition of b[j] in the C standard is that it is *((b)+(j)). So it takes the pointer b, moves j elements beyond it, and then applies *.
Since * is already applied in b[j], you do not need ->, just ..
you use . instead of -> because of this declaration of parameters:
int ball_room(ball *b, int i, int n)
b is expected to be pointer to data with type ball, so you can access it in various ways:
array way: e.g. b[5].somefield = 15 - you use dot here, because if b is of type ball *, it means that b is pointer OR it is array of objects with type b, if it's array of objects with type b (which is your case) you use . to access fields of object
pointer way: e.g. (b+5)->somefield = 15 - it will do exactly same thing as code above, but you will access data in pointer way
In C/C++ an array devolves into the address of it's first member. So when you pass the array to ball_room what actually gets passed is &ball[0].
Now inside ball_room the reverse happens. b is a pointer to ball. But here you use it as an array b[j]. So it un-devolves back into an array of structs. So what b[j] gives you is the struct and not a pointer to a struct. Consequently you access it using . instead of ->.
You can also use (b + j)->somefield. Or for even more fun how about writing j[b].somefield. The later being a really confusing left-over from the eraly compiler days when a[b] truly got turned into *(a + b) internally.
For explanation of the current issue, see Eric's answer; in some of the answers given so far there is dangerous wording applied, so just to make clear: When do we have an array and when a pointer???
Consider the following:
int a[7];
As long as we can refer to a directly, we still have an array and can use any operations that are valid on, e. g. getting size:
size_t n = sizeof(a); // size in bytes, not ints, i. e. 7*sizeof(int)
You can pass arrays to functions or even do pointer arithmetics on:
f(a);
a + 1;
In both cases, the array "decays" to a pointer, though, and the result is a pointer as well. Be aware that you can assign new values to a pointer, but not to an array itself (you can assign new values to the array's elements, directly or via pointer), so you cannot do things like ++a either.
When an array decays to a pointer, it gets a pointer to its first element:
int* ptr = a;
int* ptr = &*a; // only pointers can be dereferenced -> a decays!
int* ptr = &a[0]; // short for &*(a + 0)...
All result in exactly the same; however, the following is invalid:
int* ptr = &a;
Taking the address of an entire array actually is possible, but the resulting pointer is not of type "pointer to element" nor of type "pointer to pointer to element" (int** in the example), but of type "pointer to array of specific size". Syntax for is ugly, though, but the following would be legal again:
int(*aptr)[7] = &a;
You need to read: if I dereference ptr, I get int[7]...
Once decayed, there is only a pointer to the array left (more precisely: to one of the array elements, directly after decaying, to the first; array and first element always share the same address, so, although of different type, both pointers ptr and aptr from above hold exactly the same value). Pointers can be moved around within the array, but they do not hold as much information as the array itself, especially, the array size gets lost. This is why one needs to pass the array's length together with the pointer to functions (if needed; another variant is a sentinel value denoting the array end such as the terminating null character in strings or the null pointer following the string arguments in main's arguments list):
int a[7];
f(a, sizeof(a)/sizeof(*a)); // division: sizeof is in bytes, dividing by size
// of first element gives number of elements
Possibly with f as:
void f(int b[], size_t n)
// ^^^^^^^ in function parameter lists, just alternative syntax for int* b !!!
// however, we can show more explicitly that we expect a pointer
// to an array this way...
{
size_t m = sizeof(b); // as b is a POINTER, gives the constant (but hardware specific!)
// size of a pointer (on typical modern 64-bit hardware 8 bytes),
// no matter what size of the array being pointed to is!!!
while(n)
{
*b++ = n--;
// ^^ advances pointer, NOT array!
}
}
Hope this helps to avoid confusion.
In C, the array name is a pointer to array’s first element, hence your function declaration has name ball *band works when you pass a ball[] instance.
Try dynamically allocating the memory by using malloc() and passing that pointer to your function.
I'm learning about dynamic memory at the moment, but my book is not clear about this. Why does the declaration of the dynArray doesn't not have the [ ] brackets which is used for array declaration when not using malloc. Why is the [ ] not needed when declaring, but needed in the loop.
int * dynArray;
dynArray = malloc(sizeof(int)*5);
srand ( time(NULL) );
for(i=0; i<=myInt; i++){
dynArray[i] = rand()%100;
}
It is not needed in the loop; pointers can be accessed as arrays and arrays can be accessed as pointers
This is equivalent
for(i=0; i<=myInt; i++){
*(dynArray+i) = rand()%100;
}
The difference is in when its address is known.
For a simple int a[5] array, the compiler knows where it is, so its address is constant (or stack- or struct-relative, which is the same thing).
OTOH int* a means a is just a variable, not a constant, that happens to point to one or more int. The running program can do its own allocation and set a, and it's up to the programmer to know what he/she is doing.
But indexing a[i] works the same in either case. It takes a as the address of the array, then adds to it i times the size of an int, and that's the address of the actual integer.
This defines an array of a certain size:
int array1[10];
This defines a pointer to integer:
int * array2;
Both definitions allocate some memory. The first one allocates space to hold 10 ints. The second one allocates space to hold a pointer to integer.
When the array1 is used in an expression as an rvalue, it degenerates to a pointer. So using array1 rvalue is equivalent to taking its address: &array1. In an expression, array1 and array2 rvalues are equivalent: they act as pointer-to-int values. The difference is that you can't use array1 as an lvalue: you can't assign to it, and you can't modify it - because it's not a pointer you can write to. You can certainly, of course, modify the values pointed-to by either array1-acting-as-a-pointer, or by array2.
Both definitions above give you uninitialized variables: the contents of array1 are not defined, neither are the contents of array2. So, for example, it'd be an error to dereference the array2 pointer before a value was assigned to it.
You can set array2 to the address of the 10 integer-long area allocated in array1, and both are then equivalent:
int array1[10];
int * array2 = array1;
array1[0] = 1;
array2[0] ++; // Increment the first item of the array
assert(array1[0] == 2);
But while you can certainly make array2 point to the second item in the first array, you can't change where array1 points to:
array2 ++; // Increment the pointer so that it points to the second item of the array
assert(array2 == &array1[1]);
array1 ++; // Triggers a compile-time error diagnostic
The assert, from #include <assert.h>, is simply a way to assert certain facts. If they prove false at runtime, the program will abort. It's also a way to succinctly express, in the C language, that certain things are true at certain points in the program. It's better than writing comments, since the assertion will be checked for you in a debug build, at runtime.