I'm using D and interfacing with some C libraries. As a result I have to convert D arrays to pointers for C (ex. short*). Currently I just cast them like this:
int[] dArray = [0, 1, 2, 3, 4];
myCFunction(cast(int*) dArray);
Is this unsafe? I tried to do:
myCFunction(&dArray);
But doing that gives the function an int[]* instead of int*. I see that in C++ some people take the first element like this:
myCFunction(&dArray[0]);
But wouldn't that pointer only point to the first element? I am new to pointers and references as I have come from the world of Java.
How would I convert an array to a pointer so I can pass it to a C function?
In D, an array is actually (conceptually) this:
struct {
size_t length;
void* ptr;
};
The usual way of getting a pointer from an array is to use the .ptr field. In your case: myCFunction(dArray.ptr);
But wouldn't that pointer only point to the first element
Because the elements are stored contiguously in memory, a pointer to the first element is all we need. We just add an offset to that pointer if we want to get the addresses of other elements.
One other point: usually if a C function wants an array pointer, it also has an argument for the array length. In most cases you can give it dArray.length, but sometimes it's actually asking for the size in bytes, rather than the number of elements.
Related
Consider
float a[] = { 0.1, 0.2, 0.3};
I am quite confused about the fact that a is later passed to a function foo(float* A). Shouldn't a variable of type float* point to a single float, right? Like what is mentioned in this tutorial
Good question.
float * does point to a single float value.
However, in C, you can do pointer arithmetic. So, when you get the value from the first pointer, you can actually go to the next float in memory.
And in an array, all of the floats are laid out contiguously in memory.
So, in order to access the whole array, you just need to get the pointer to the first element in the array and iterate till the end of the array. This is why the size of the array is also passed to the function along with the pointer to the first element of the array.
void do_stuff(float * a, int n)
{
for(int i=0; i<n; ++i)
{
do_stuff_with_current_element(a[i]);
}
}
In C, arrays are contiguous chunks of memory, which means every element is next to each other in memory. So, a pointer to the first element combined with the knowledge of the type of the element lets you denote an array with just a pointer to the first element. Note that this does not include information on length, which is why many C functions that deal with arrays (like memcpy) also take a parameter for the length.
The pointer reaches the base adress and checks the type of your variable. Every step it sums with your variable byte. So in real you have just your base adress and variable information.
A float* variable (when properly initialized or assigned) does, indeed, point to a single float variable. However, that single variable could be the first element of an array of float data.
Further, when you give an array as an argument to a function, the array implicitly decays to a pointer to its first element. So, calling your foo function with the array, a, as its parameter, is passing a pointer to that array's first element (a float item) - so the argument fully satisfies the function's requirement to take a "pointer-to-float" parameter.
Do I need to do type casting when I want to index a specific array element of a two dimensional array manually with pointer arithmetic.If so why? Here's what I mean:
float *p;
float balance[5][2]={2.34,
5.66,7.85,12.56,9.87,76.22,56.55,21.02,66.12,10.001};
p=(float *) balance; //Do I need this type casting and if so why?
printf("%.2f",*(p+(3*2)+1));
Balance is a 2D array that is an array of arrays. It will decay like any array to a pointer to its first element... but that element is still an array and not a float!
That is the reason why you need a cast here, but in fact casting a pointer to an array to a pointer to its first element is not really standard wise. The correct way is to dereference balance: it will be an 1D array which will nicely decay to a pointer to the first float:
p = *balance; // no cast required here
That being said, on a pedantic point of view, the next line (*(p+(3*2)+1)) aliases a 2D 2x5 array to an 1D array of size 10. The result is undefined per the standard as soon as the index is larger that the row size here 2. Of course all common implementation allow it for compatibility with old code, but you really should wonder why you need it and avoid that if you can.
The correct and conformant way would be:
float (*pp)[2];
float balance[5][2] = { 2.34,
5.66,7.85,12.56,9.87,76.22,56.55,21.02,66.12,10.001 };
pp = balance;
printf("%.2f\n", pp[3][1]);
I started learning C recently, and I'm having a problem understanding pointer syntax, for example when I write the following line:
int ** arr = NULL;
How can I know if:
arr is a pointer to a pointer of an integer
arr is a pointer to an array of pointers to integers
arr is a pointer to an array of pointers to arrays of integers
Isn't it all the same with int ** ?
Another question for the same problem:
If I have a function that receives char ** s as a parameter, I want to refer to it as a pointer to an array of strings, meaning a pointer to an array of pointers to an array of chars, but is it also a pointer to a pointer to a char?
Isn't it all the same with int **?
You've just discovered what may be considered a flaw in the type system. Every option you specified can be true. It's essentially derived from a flat view of a programs memory, where a single address can be used to reference various logical memory layouts.
The way C programmers have been dealing with this since C's inception, is by putting a convention in place. Such as demanding size parameter(s) for functions that accept such pointers, and documenting their assumptions about the memory layout. Or demanding that arrays be terminated with a special value, thus allowing "jagged" buffers of pointers to buffers.
I feel a certain amount of clarification is in order. As you'd see when consulting the other very good answers here, arrays are most definitely not pointers. They do however decay into ones in enough contexts to warrant a decades long error in teaching about them (but I digress).
What I originally wrote refers to code as follows:
void func(int **p_buff)
{
}
//...
int a = 0, *pa = &a;
func(&pa);
//...
int a[3][10];
int *a_pts[3] = { a[0], a[1], a[2] };
func(a_pts);
//...
int **a = malloc(10 * sizeof *a);
for(int i = 0; i < 10; ++i)
a[i] = malloc(i * sizeof *a[i]);
func(a);
Assume func and each code snippet is compiled in a separate translation unit. Each example (barring any typos by me) is valid C. The arrays will decay into a "pointer-to-a-pointer" when passed as arguments. How is the definition of func to know what exactly it was passed from the type of its parameter alone!? The answer is that it cannot. The static type of p_buff is int**, but it still allows func to indirectly access (parts of) objects with vastly different effective types.
The declaration int **arr says: "declare arr as a pointer to a pointer to an integer". It (if valid) points to a single pointer that points (if valid) to a single integer object. As it is possible to use pointer arithmetic with either level of indirection (i.e. *arr is the same as arr[0] and **arr is the same as arr[0][0]) , the object can be used for accessing any of the 3 from your question (that is, for second, access an array of pointers to integers, and for third, access an array of pointers to first elements of integer arrays), provided that the pointers point to the first elements of the arrays...
Yet, arr is still declared as a pointer to a single pointer to a single integer object. It is also possible to declare a pointer to an array of defined dimensions. Here a is declared as a pointer to 10-element array of pointers to arrays of 10 integers:
cdecl> declare a as pointer to array 10 of pointer to array 10 of int;
int (*(*a)[10])[10]
In practice array pointers are most used for passing in multidimensional arrays of constant dimensions into functions, and for passing in variable-length arrays. The syntax to declare a variable as a pointer to an array is seldom seen, as whenever they're passed into a function, it is somewhat easier to use parameters of type "array of undefined size" instead, so instead of declaring
void func(int (*a)[10]);
one could use
void func(int a[][10])
to pass in a a multidimensional array of arrays of 10 integers. Alternatively, a typedef can be used to lessen the headache.
How can I know if :
arr is a pointer to a pointer of an integer
It is always a pointer to pointer to integer.
arr is a pointer to an array of pointers to integers
arr is a pointer to an array of pointers to arrays of integers
It can never be that. A pointer to an array of pointers to integers would be declared like this:
int* (*arr)[n]
It sounds as if you have been tricked to use int** by poor teachers/books/tutorials. It is almost always incorrect practice, as explained here and here and (
with detailed explanation about array pointers) here.
EDIT
Finally got around to writing a detailed post explaining what arrays are, what look-up tables are, why the latter are bad and what you should use instead: Correctly allocating multi-dimensional arrays.
Having solely the declaration of the variable, you cannot distinguish the three cases. One can still discuss if one should not use something like int *x[10] to express an array of 10 pointers to ints or something else; but int **x can - due to pointer arithmetics, be used in the three different ways, each way assuming a different memory layout with the (good) chance to make the wrong assumption.
Consider the following example, where an int ** is used in three different ways, i.e. p2p2i_v1 as a pointer to a pointer to a (single) int, p2p2i_v2 as a pointer to an array of pointers to int, and p2p2i_v3 as a pointer to a pointer to an array of ints. Note that you cannot distinguish these three meanings solely by the type, which is int** for all three. But with different initialisations, accessing each of them in the wrong way yields something unpredictable, except accessing the very first elements:
int i1=1,i2=2,i3=3,i4=4;
int *p2i = &i1;
int **p2p2i_v1 = &p2i; // pointer to a pointer to a single int
int *arrayOfp2i[4] = { &i1, &i2, &i3, &i4 };
int **p2p2i_v2 = arrayOfp2i; // pointer to an array of pointers to int
int arrayOfI[4] = { 5,6,7,8 };
int *p2arrayOfi = arrayOfI;
int **p2p2i_v3 = &p2arrayOfi; // pointer to a pointer to an array of ints
// assuming a pointer to a pointer to a single int:
int derefi1_v1 = *p2p2i_v1[0]; // correct; yields 1
int derefi1_v2 = *p2p2i_v2[0]; // correct; yields 1
int derefi1_v3 = *p2p2i_v3[0]; // correct; yields 5
// assuming a pointer to an array of pointers to int's
int derefi1_v1_at1 = *p2p2i_v1[1]; // incorrect, yields ? or seg fault
int derefi1_v2_at1 = *p2p2i_v2[1]; // correct; yields 2
int derefi1_v3_at1 = *p2p2i_v3[1]; // incorrect, yields ? or seg fault
// assuming a pointer to an array of pointers to an array of int's
int derefarray_at1_v1 = (*p2p2i_v1)[1]; // incorrect; yields ? or seg fault;
int derefarray_at1_v2 = (*p2p2i_v2)[1]; // incorrect; yields ? or seg fault;
int derefarray_at1_v3 = (*p2p2i_v3)[1]; // correct; yields 6;
How can I know if :
arr is a pointer to a pointer of an integer
arr is a pointer to an array of pointers to integers
arr is a pointer to an array of pointers to arrays of integers
You cannot. It can be any of those. What it ends up being depends on how you allocate / use it.
So if you write code using these, document what you're doing with them, pass size parameters to the functions using them, and generally be sure about what you allocated before using it.
Pointers do not keep the information whether they point to a single object or an object that is an element of an array. Moreover for the pointer arithmetic single objects are considered like arrays consisting from one element.
Consider these declarations
int a;
int a1[1];
int a2[10];
int *p;
p = &a;
//...
p = a1;
//...
p = a2;
In this example the pointer p deals with addresses. It does not know whether the address it stores points to a single object like a or to the first element of the array a1 that has only one element or to the first element of the array a2 that has ten elements.
The type of
int ** arr;
only have one valid interpretation. It is:
arr is a pointer to a pointer to an integer
If you have no more information than the declaration above, that is all you can know about it, i.e. if arr is probably initialized, it points to another pointer, which - if probably initialized - points to an integer.
Assuming proper initialization, the only guaranteed valid way to use it is:
**arr = 42;
int a = **arr;
However, C allows you to use it in multiple ways.
• arr can be used as a pointer to a pointer to an integer (i.e. the basic case)
int a = **arr;
• arr can be used as a pointer to a pointer to an an array of integer
int a = (*arr)[4];
• arr can be used as a pointer to an array of pointers to integers
int a = *(arr[4]);
• arr can be used as a pointer to an array of pointers to arrays of integers
int a = arr[4][4];
In the last three cases it may look as if you have an array. However, the type is not an array. The type is always just a pointer to a pointer to an integer - the dereferencing is pointer arithmetic. It is nothing like a 2D array.
To know which is valid for the program at hand, you need to look at the code initializing arr.
Update
For the updated part of the question:
If you have:
void foo(char** x) { .... };
the only thing that you know for sure is that **x will give a char and *x will give you a char pointer (in both cases proper initialization of x is assumed).
If you want to use x in another way, e.g. x[2] to get the third char pointer, it requires that the caller has initialized x so that it points to a memory area that has at least 3 consecutive char pointers. This can be described as a contract for calling foo.
C syntax is logical. As an asterisk before the identifier in the declaration means pointer to the type of the variable, two asterisks mean pointer to a pointer to the type of the variable.
In this case arr is a pointer to a pointer to integer.
There are several usages of double pointers. For instance you could represent a matrix with a pointer to a vector of pointers. Each pointer in this vector points to the row of the matrix itself.
One can also create a two dimensional array using it,like this
int **arr=(int**)malloc(row*(sizeof(int*)));
for(i=0;i<row;i++) {
*(arr+i)=(int*)malloc(sizeof(int)*col); //You can use this also. Meaning of both is same. //
arr[i]=(int*)malloc(sizeof(int)*col); }
There is one trick when using pointers, read it from right hand side to the left hand side:
int** arr = NULL;
What do you get: arr, *, *, int, so array is a pointer to a pointer to an integer.
And int **arr; is the same as int** arr;.
int ** arr = NULL;
It's tell the compiler, arr is a double pointer of an integer and assigned NULL value.
There are already good answers here, but I want to mention my "goto" site for complicated declarations: http://cdecl.org/
Visit the site, paste your declaration and it will translate it to English.
For int ** arr;, it says declare arr as pointer to pointer to int.
The site also shows examples. Test yourself on them, then hover your cursor to see the answer.
(double (^)(int , long long ))foo
cast foo into block(int, long long) returning double
int (*(*foo)(void ))[3]
declare foo as pointer to function (void) returning pointer to array 3 of int
It will also translate English into C declarations, which is prety neat - if you get the description correct.
I have this code:
int a[2][3]={{1,2},{1,3,4}};
int b[2][3]={{4,6},{22,33,55}};
int (*comb1[4])[3]={a,b,a,b};//works
int (*comb2[4])[2][3]={a,b,a,b};//it gives me warning: initialization from incompatible pointer type
Quoting http://cdecl.org/:
1.declare comb1 as array 4 of pointer to array 3 of int
2.declare comb2 as array 4 of pointer to array 2 of array 3 of int
I want to use the comb as 3dim array, where the first dimension selects the pointer of [2][3] and the rest identify the element.
This is achieved by comb1, is it possible to achieve something similar using in the inside of the declaration the [2][3]. (like what I have tried to do with comb2 without success. At the end I want to use e.g. comb2[0][0][0])
I'm assuming you want a pointer to a two-dimensional array. Your second declaration is correct (for an array of those), but your initializer is wrong: a and b are arrays, not pointers to arrays.
Fix:
int (*ab[4])[2][3]={&a,&b,&a,&b};
If you want to use comb[0][0][0] to access the first element of a, andcomb[1][0][0] to access the first element of b, you should use comb1 from your question:
int (*comb[4])[3] = {a, b, a, b};
This might be confusing, since comb is supposed to contain pointers to a and b, which are 2x3 matrices, not arrays of 3 ints, as this declaration seems to indicate. Shouldn't the number 2 be somewhere in there?
But remember that arrays are second-class citizens in C, and in most cases they are handled not as actual arrays, but as pointers to the first element in the array. This is also true concerning pointers to arrays. In general you don't use pointer to array, but pointer to the first element of the array. The address would be the same, but the data types are different. Here is a simpler example:
float a[17]; // This is an array of 17 floats
float *p = a; // This is just a pointer to float, not to array of floats
a[0] = 3.14; // Setting the first element of a
p[0] = 3.14; // Setting the same element, through p
Note that there is no "17" in the declaration of p.
You can use a pointer to the array, but then you need an extra level of indirection, to follow that pointer and get the right data type:
float (*pa)[17] = &a; // Pointer to array of 17 floats
(*pa)[0] = 3.14; // Setting the first element of a, through pa
You could write pa[0][0] instead of (*pa)[0], since a[0] in C is equivalent to *a, but that would be misleading, since it would give the impression of there being a two-dimensional array, when all you have is a pointer to a single-dimensional array.
What might be really confusing is that in the code above, pa, *pa and a will all be the same memory address:
printf("a = %p\n", (void*)a);
printf("pa = %p\n", (void*)pa);
printf("*pa = %p\n", (void*)(*pa));
Output when I ran it on my computer:
a = 0x7fff875a07e0
pa = 0x7fff875a07e0
*pa = 0x7fff875a07e0
Since arrays are a bit special, pointers to arrays are a bit special too. If a is an array, both a and &a (when used in most contexts) give the same address (but different data types). And in reverse: If p is a pointer to an array, both p and *p give the same address (but different data types).
In summary: If you think that since a is 2x3 matrix, the declaration of comb should somehow say both 2 and 3, and not just 3, that is misguided.
You can do so, if you absolutely want to, as melpomene has shown. But in that case you need to write an extra pointer indirection: (*comb[0])[0][0].
I am trying to understand basic concepts in C. I have two questions :
1.Why will the following piece of code work and the other does not?
/* This works fine */
typedef int SortTableRows[20];
SortTableRows* SortTableRowsPtr;
/* This will give error --> subscripted value is neither array nor pointer*/
int SortTableRows[20];
SortTableRows* SortTableRowsPtr;
Second question is what is the third line of code doing?
typedef int SortTableRows[20];
SortTableRows* SortTableRowsPtr;
SortTableRowsPtr[2][3]=2; //Why the compiler doesnt give any error?how can we use a pointer as a 2d array.
You've defined SortTableRows to be an array of ints with int SortTableRows[20]. That identifier is now fixed as an array, it cannot be used for anything else. You're then trying to use it as a type to declare a pointer (I think). If you want to declare a pointer to an array of ints you would do it like this:
int *SortTableRowsPtr;
SortTablesRowPtr = SortTablesRows;
In the second question, you're assigning a value to a pointer to a pointer that you're treating as a two dimensional array, which makes no real difference to your compiler (though it makes no real sense in this context), as 'multidimensional' arrays are stored in memory in a linear way, the same as single dimension arrays. Your typedef doesn't make any real sense here, as you're defining a type of array, then making an uninitialised pointer to it (this creates an int **), and accessing it as if it points to something valid (which will compile, but would surely crash).
To have this work you'd need to define an array of 20 ints and then point to it:
SortTablesRows table[10] = {}; // equivalent to int table[10][20];
SortTablesRowPtr = table;
This works because you're declaring a pointer to an array of 20 ints, i.e.
int (*SortTablesRowPtr)[20];
I've expanded this answer. It helps to explain it more simply step by step. Take a table of 3 rows and 10 columns. That's defined:
int table[3][10];
You can then set a pointer to this table. Because it's in two dimensions this isn't right:
int *ptr = table; // wrong - incompatible pointer
But this would point to the second row (and the first column):
int *ptr = table[1];
In other words you want a pointer to an array of 10 ints, i.e. you want a pointer that points to a type of int n[10]. To do this you can write:
int (*ptr2)[10] = table;
Now you can use ptr2 to access the table directly, either as pointers, arrays, or both. As it stands it points to the first row and first column. If you add one to ptr2 it will select the next row.
ptr2[1][3] = 3; // change row 2, column 4
(*(ptr2 + 1))[4] = 10 // row 2, column 5 (yuck)
Question 1.
In the first you are telling it that SortTablesRow is an array of 20 ints. So SortTablesRow is a type. In the second you are creating a variable called SortTablesRow which is an array of 20 ints. This can't be used as a type because its a variable.
Question 2.
Here you are typedef'ing SortTablesRow to be an array of 20 ints. You then say SortTablesRowPtr is a pointer to it. So now you have a pointer to an array of 20 ints. This is essentially an int**. So the first array index is indexing the first pointer and the second array index is indexing the second pointer (or the array) and thus looking up in the 20 element int array.