This is my function
int mkvCopyWord(uint8_t *pBuffer, UINT8 temp):
main()
{
uint8_t a[10];
mkvCopyWord(&a,10);
}
its says warning : note: expected ‘uint8_t *’ but argument is of type ‘uint8_t (*)[10]’
how to remove this warning..?
Your syntax for passing a pointer-to-array is fine. But you are trying to pass it to something that doesn't want a pointer-to-array. It just wants a pointer to the beginning element. The simplest way to get that is to allow the array name to decay to a pointer, thus mkvCopyWord(a, 10). The function will assume that the pointer you give it is pointing to some sequence of uint8_ts somewhere - that is why you have to pass the array size as another parameter, because it does not know about the array, it only has some address in memory where the array is.
You don't need to take the address of the array as it implicitly converts to a pointer:
int mkvCopyWord(uint8_t *pBuffer, UINT8 temp):
main()
{
uint8_t a[10];
mkvCopyWord(a,10);
}
int main(void) //main() without return type isn't a good practice
{
uint8_t a[10];
mkvCopyWord(&a,10);
return 0;
}
Here you pass a parameter of type "pointer to array of 10 uint8_t". Your function, however, is declared to take pointer to int. In order to make this syntax work, you'd have to change the declaration of your function to take a pointer to an array of 10 uint8_t's
void mkvCopyWord(uint8_t (*parr)[10], int n)
This is all about syntax and type system. As for your actual problem, you need to pass a pointer to the first element of your array.
mkvCopyWord(&a[0],10);
However, an array is implicitly converted to that anyway, so you don't need to bother. You use the following:
mkvCopyWord(a,10);
HTH
Remove the ampersand in mkvCopyWord(&a,10):
int mkvCopyWord(uint8_t *pBuffer, UINT8 temp):
main()
{
uint8_t a[10];
mkvCopyWord(a,10); /* <<< removed the ampersand */
}
There is quite a lot of information on the equivalence of pointers and arrays in the C FAQ.
Related
How can I pass the location of an array of pointers in a function in c i.e.
I have an int* array[10]; and through a function I want to assign the array[0] to be the location of a particular number say, 5. What should the argument of the function look like. I have tried:
void insert(int* array);
but it didn't work.
Arrays are always passed as a pointer pointing to the beginning of the array, even if you don't write it explicitly. So given this declaration of an array from your question:
int *array[10];
Both the following functions will accept a pointer to such an array:
int foo(int *array[]);
int foo(int **array);
They are just equivalent and I would suggest you use the second form, because it makes it explicit what type really is passed to the function.
inside the function, you can access any element, because the indexers are define the same way on a pointer to an array as on the array itself:
int foo(int **array)
{
int *sixthElement = array[5];
// [...]
}
Additional stylistic note: In C, it's common practice to attach the * when declaring a pointer to the identifier, not to the type, ie better write
int *array[10];
instead of
int* array[10];
This is because in a C declaration, there's no such thing as a pointer type, there's a pointer declarator (consisting of the *, optional qualifiers and the identifier) and this declarator declares a variable to be a pointer to the specified type. It's a subtle difference, but if you ever try to declare more than one variable in one line (don't do this, it's just for explanation here), you will notice it:
int *a, b; // <- declares a as a pointer to int, b just as an int
struct grid {
int width, height;
void *cells[];
};
typedef struct grid grid;
int main(){
enum { width = 2, height = 10 };
grid *g = malloc(sizeof(grid) + width * height * sizeof(void *));
void *(*cells)[10] = &g->cells;
}
My professor taught us about this cool way to allocate a flexible array and then assign a pointer that points to an entire array of pointers
void *(*cells)[10] = &g->cells; <-- This line
So i tried this method
char *array[10];
char *(*pointer)[2] = &array;
And it just gave me a compiler error
warning: incompatible pointer types initializing
'char *(*)[2]' with an expression of type 'char *(*)[10]'
[-Wincompatible-pointer-types]
char *(*pointer)[2] = &array;
If anyone could explain to me the functionality of a "pointer to an entire array"
that would be useful. Thank you
Lets take your correct declaration first:
void *(*cells)[10] = &g->cells;
To understand this, recognize first that cells is the identifier being declared, and from there follow precedence rules:
(*cells) says that cells is a pointer, and the rest of the declaration describes the pointed-to thing. The parentheses are simply to enforce precedence, just like in an arithmetic expression.
The [10] applies next, because brackets have higher precendence than unary *. This says, then, that (*cells) is an array with 10 elements.
That leaves the void * out front, which gives the type of each element.
And if we look at &g->cells, it is a pointer to an array of an unspecified number of void *.
Now consider your code:
char *array[10];
char *(*pointer)[2] = &array;
Following similar procedure, we get that pointer is declared as a pointer to an array of 2 char *. So far, so good. Now, what are you trying to assign to it? Why, it's a pointer to an array of 10 char *. That's a pointer to a different, incompatible type.
In the first case, the initializer's type is a pointer to an "incomplete type" that is compatible with the type to which the pointer points. (It is incomplete because the array length is unspecified; it is compatible because in all other respects it matches the other type.) The pointed-to thing could be an array of the length implicitly asserted by the assignment, and C will treat the pointer as if it were.
In the second case, C can see that the two pointers definitely point to objects of different size, and that therefore the assignment is definitely incorrect. You would need a cast or a change to the type of pointer to make it accept the initialization.
&array is the address of an array containing 10 pointers to char
pointer is a pointer to an array containing 2 pointers to char
2 != 10
,
hence the warning.
There's a handy website that helps to understand difficult c decelerations.
I need to pass into a function the address of a character pointer array, what would be the correct function declaration/prototype syntax for that?
I tried:
void myFunc(char &*a[]);
But get an expected ; , or ) before & error.
I also tried:
void myFunc(char **a);
Since the pointer I would be passing in is indeed a pointer to a pointer, but I get yet another error. This time the error has to do with: expected char **, but got char *[]
Or something like that. I have since attempted other solutions so I not remember exactly the error.
Any suggestions?
Assuming you have an array declared as
char *a[N];
and you want to pass a pointer to the array, as in
foo( &a );
then the prototype for foo needs to be
void foo( char *(*aptr)[N] );
Note that in this case, the size of the array must be declared; a pointer to an N-element array is a different type from a pointer to an M-element array.
Normally, you don't want to do this; instead, you would normally just pass the array expression like so:
foo ( a );
and the corresponding prototype would be:
void foo ( char **aptr );
Except when it is the operand of thesizeof or unary & operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer toT", and the value of the expression will be the address of the first element of the array.
Updated Answer For Modified Problem Statement
Given what you have said in comments, there is no need to pass a pointer to an array. You can simply pass a pointer to the first element of the array. Such a pointer suffices because the remaining elements of the array are obviously located after the first element.
To write a function that sets pointers in an array of pointers to char, do this:
void MyFunction(int NumberToSet, char *Pointers[])
{
for (int i = 0; i < NumberToSet; ++i)
{
Pointers[i] = SomeString;
}
}
In the above, SomeString must have type “pointer to char”. This could be a string, such as "Hello", or an array of char (which is automatically converted to a pointer to char), or some identifier x that has been declared as char *x (and has been initialized or assigned), for example.
To use this function, call it like this:
char *MyArrayOfPointers[SomeNumber];
MyFunction(NumberOfPointersIWantToSet, MyArrayOfPointers);
Original Answer
In most cases, to pass an array of pointers to char to a function, it suffices to pass the address of the first element. In this case, you would use either of these (they are equivalent):
void myFunc(char **a)
void myFunc(char *a[])
If you truly want to pass the address of the array, you would use:
void myFunc(char *(*a)[])
In this case, the type of a is incomplete, since the dimension is missing. Depending on what you intend to do with a, you may need to provide the dimension in the declaration.
When calling myFunc and passing it some array declared as char *array[N];, you would pass it, in the former case, as myFunc(array) and, in the latter case, as myFunc(&array).
try this as a function definition void myFunc(char *a[]) or void myFunc(char **a) then use it this way :
char *arr[20];
myFunc(arr);
Ok you are almost on the right path. void myFunc(char *a[]);
Example
void fun(char *a[]){
printf("%s",*a); //for accessing the next element do a+1
}
int main(void) {
char *x[3];
x[0]="abcd";
fun(x); // here you are passing the address first array element
return 0;
DEMO
Declaration
void myFunc(char &*a[]);
is not a valid C syntax.
To pass the address of character pointer arrays, use this instead
void myFunc(char *(*a)[]);
*(*a)[] in the above function declares a as pointer to array of pointers to chars. Must note that a has an incompatible type. A suffix is needed in [] to make it complete.
First of all, C is in general a "pass by reference" language. Some data items such as integers, floats, and single characters can be passed by value. But, arrays of those same data types are ALWAYS passed by reference.
Thus, when you say "I need to pass into a function the address of a character pointer array" then simply declare an array of character pointers in your function prototype as:
void myFunc(char *a[]);
Thus, char * declares a char pointer and a[] defines an array of them. To check this declaration refer to: http://www.cdecl.org/ which parses this expression as a "declare a as array of pointer to char".
The technical point is that the * binds with char rather than with a[].
So, C will pass a pointer to the data structure that you have declared. A discussion on this topic could delve into double pointers but for this question such a discussion is probably off topic.
I think that it is because the former is an array of pointers to char and the latter is a pointer to an array of chars, and we need to properly specify the size of the object being pointed to for our function definition. In the former;
function(char * p_array[])
the size of the object being pointed to is already included (its a pointer to char), but the latter
function(char (*p_array)[])
needs the size of the array p_array points to as part of p_array's definition?
I'm at the stage where I've been thinking about this for too long and have just confused myself, someone please let me know if my reasoning is correct.
Both are valid in C but not C++. You would ordinarily be correct:
char *x[]; // array of pointers to char
char (*y)[]; // pointer to array of char
However, the arrays decay to pointers if they appear as function parameters. So they become:
char **x; // Changes to pointer to array of pointer to char
char (*y)[]; // No decay, since it's NOT an array, it's a pointer to an array
In an array type in C, one of the sizes is permitted to be unspecified. This must be the leftmost one (whoops, I said rightmost at first). So,
int valid_array[][5]; // Ok
int invalid_array[5][]; // Wrong
(You can chain them... but we seldom have reason to do so...)
int (*convoluted_array[][5])[][10];
There is a catch, and the catch is that an array type with [] in it is an incomplete type. You can pass around a pointer to an incomplete type but certain operations will not work, as they need a complete type. For example, this will not work:
void func(int (*x)[])
{
x[2][5] = 900; // Error
}
This is an error because in order to find the address of x[2], the compiler needs to know how big x[0] and x[1] are. But x[0] and x[1] have type int [] -- an incomplete type with no information about how big it is. This becomes clearer if you imagine what the "un-decayed" version of the type would be, which is int x[][] -- obviously invalid C. If you want to pass a two-dimensional array around in C, you have a few options:
Pass a one-dimensional array with a size parameter.
void func(int n, int x[])
{
x[2*n + 5] = 900;
}
Use an array of pointers to rows. This is somewhat clunky if you have genuine 2D data.
void func(int *x[])
{
x[2][5] = 900;
}
Use a fixed size.
void func(int x[][5])
{
x[2][5] = 900;
}
Use a variable length array (C99 only, so it probably doesn't work with Microsoft compilers).
// There's some funny syntax if you want 'x' before 'width'
void func(int n, int x[][n])
{
x[2][5] = 900;
}
This is a frequent problem area even for C veterans. Many languages lack intrinsic "out-of-the-box" support for real, variable size, multidimensional arrays (C++, Java, Python) although a few languages do have it (Common Lisp, Haskell, Fortran). You'll see a lot of code that uses arrays of arrays or that calculates array offsets manually.
NOTE:
The below answer was added when the Q was tagged C++, and it answers from a C++ perspective. With tagged changed to only C, both the mentioned samples are valid in C.
Yes, Your reasoning is correct.
If you try compiling the error given by compiler is:
parameter ‘p_array’ includes pointer to array of unknown bound ‘char []’
In C++ array sizes need to be fixed at compile time. C++ standard forbids Variable Lenght Array's(VLA) as well. Some compilers support that as an extension but that is non standard conforming.
Those two declarations are very different. In a function parameter declaration, a declarator of [] directly applied to the parameter name is completely equivalent to a *, so your first declaration is exactly the same in all respects as this:
function(char **p_array);
However, this does not apply recursively to parameter types. Your second parameter has type char (*)[], which is a pointer to an array of unknown size - it is a pointer to an incomplete type. You can happily declare variables with this type - the following is a valid variable declaration:
char (*p_array)[];
Just like a pointer to any other incomplete type, you cannot perform any pointer arithmetic on this variable (or your function parameter) - that's where you error arises. Note that the [] operator is specified as a[i] being identical to *(a+i), so that operator cannot be applied to your pointer. You can, of course, happily use it as a pointer, so this is valid:
void function(char (*p_array)[])
{
printf("p_array = %p\n", (void *)p_array);
}
This type is also compatible with a pointer to any other fixed-size array of char, so you can also do this:
void function(char (*p_array)[])
{
char (*p_a_10)[10] = p_array;
puts(*p_a_10);
}
...and even this:
void function(char (*p_array)[])
{
puts(*p_array);
}
(though there is precious little point in doing so: you might as well just declare the parameter with type char *).
Note that although *p_array is allowed, p_array[0] is not.
Because,
(1) function(char * p_array[])
is equivalent to char **p_array; i.e. a double pointer which is valid.
(2) function(char (*p_array)[])
You are right, that p_array is pointer to char array. But that needs to be of fixed size in the case when it appears as function argument. You need to provide the size and that will also become valid.
can we declare a function in a header file in following way?
extern int ap( char[][] );
can we use char[][] in function?
No, you need to specify the last N-1 dimensions for an array.
extern int ap( char[][DIMENSION] );
For more information look here
For a two dimensional array, you have to supply a size for the last dimension otherwise the compiler doesn't know how to use it. (it's fine to omit the name though.)
like this:
extern int ap( char[][10] );
char[][] is not a valid array type because you cannot have arrays of an incomplete type, and char[] is incomplete. I know that's confusing because you really have two array types, so here's another example with the same problem: char a[3][]. The array a has length 3 and element type of char[], but char[] is, again, incomplete and this is invalid.
When you have a "multidimentional array", you really have an array of arrays. For example, typedef int U[3][5]; makes U an array of length 3 of arrays of length 5 of ints and is equivalent to typedef int H[5]; typedef H U[3];.
The reason you may omit the leftmost dimension with function parameters is because, with function parameters only, array types of the form T[N] are transformed into T*, and N can be left out, giving T[] to T*. This only applies at the "topmost" or "outermost" level.
So, all these function declarations are identical:
int f1(int a[3][5]);
int f2(int a[][5]);
int f3(int (*a)[5]);
typedef int T[5];
int f4(T a[3]);
int f5(T a[]);
int f6(T* a);
You can, of course, delete the parameter name a in any of the above declarations without changing them.
Yet, it is perfectly valid to omit parameter names in function declarations. When you define the function, however, you must give the array a name, and then you can refer to it by this name.
No, this is not allowed - it attempts to declare the parameter as a pointer to an incomplete array type.
The array type must be completed with a size, like this:
extern int ap( char[][10] );