I am new to C language and I am having a problem that I really don't understand. I am trying to get an array from another function but when I try to extract the information, it gives me the following warning:
Implicit declaration of function 'getk_vector_calculation' is invalid in C99
Array initializer must be an initializer list or string literal
Here is the code:
int k_vector_calculation(int krec[3])
{
...
krec [0] = l*u[0]+m*v[0]+o*[0] ;
krec [1] = l*u[1]+m*v[1]+o*[1] ;
krec [2] = l*u[2]+m*v[2]+o*[2] ;
return k_vector_calculation( &krec[3] )
}
int main ()
{
char krec[3] = getk_vector_calculation(&krec[3]);
...
}
in your main() the function you called is getk_vector_calculation() [which is not k_vector_calculation()] and which is not declared or defined before the usage.
To resolve this,
either #include the header file containg the declaration of getk_vector_calculation() in your sorce file. [Considering getk_vector_calculation() is in some other file]
or, add a forward declaration of getk_vector_calculation() before main() and define getk_vector_calculation() somewhere.
To know more about implicit declaration, you can check this question.
EDIT:
As others have pointed out, there are many more problems in your code snippet. But since the question title is limited to implicit declaration error, IMO, this answer should do the needful. The remaining error(s) is(are) altogether a different aspect.
In older versions of C, functions that had not been declared yet were still able to be called, and it was assumed that they returned int and took an unspecified number of arguments. Strictly speaking, in C99, it is not permitted to call a function without declaring it first.
In your case however, you are trying to call a function called getk_vector_calculation but you have defined a function called k_vector_calculation (no get at the beginning).
You are also trying to initialise an array using a function, which is not permitted (in C, functions cannot return arrays). Simply declare the array and call k_vector_calculation as a separate statement, e.g.:
int krec[3] = {0};
k_vector_calculation(krec);
Don't use &krec[3] as this points to an invalid location. Use &krec[0] to provide the address of the first element in the array, or equivalently just krec will do. N.b. also that you declare an array of type char, but your function accepts a pointer to int, and these types are not compatible. Your function also calls itself unconditionally so there is a guaranteed infinite recursion if the snipped out code does not conditionally return. If your function doesn't need to call itself, and it doesn't return a value of any importance, change the return type to void to indicate it has no return value.
Since you are using C99, you can take advantage of using the static keyword in your function's parameter declaration:
void k_vector_calculation(int krec[static 3])
{
// ... other code here ...
krec[0] = l*u[0]+m*v[0]+o*[0];
krec[1] = l*u[1]+m*v[1]+o*[1];
krec[2] = l*u[2]+m*v[2]+o*[2];
}
The above code declares a function that takes as an argument an array of at least 3 int.
Several issues, here:
As Sourav Ghosh pointed out, you define k_vector_calculation(), but then try to call getk_vector_calculation(). You have to use the right names.
You say you want to "get an array from another function" - you just can't do this in C.
You don't show all your code for k_vector_calculation(), but as shown, this function will call itself forever, because the last thing it does is to unconditionally call itself again. If you have a recursive function, you need to give it a way to terminate.
&krec[3] is the address of the fourth element of the array k, which is not want you want to be doing, here, especially since your array only contains 3 elements. To refer to the array itself, just use krec.
char krec[3] = getk_vector_calculation(&krec[3]); is invalid for numerous reasons. One, you can't initialize arrays in this way in C. Two, see point (4) for your argument. Three, even if you could initialize arrays this way in C, you'd be trying to pass an uninitialized array to a function, initialize it in there, and then try to initialize your original array with the result. It just makes no sense.
You also write your functions to work with an array of int, but declare krec in main() as an array of char.
It's not clear what you want k_vector_calculation() to do, but you just can't return arrays in C like that. Probably what you want to do is just pass the array to the function, have the function work on in, and return nothing. For instance:
#include <stdio.h>
void k_vector_calculation(int kvec[])
{
kvec[0] = 1;
kvec[1] = 2;
kvec[2] = 3;
}
int main(void)
{
int kvec[3];
k_vector_calculation(kvec);
for ( int i = 0; i < 3; ++i ) {
printf("kvec[%d] is %d.\n", i, kvec[i]);
}
return 0;
}
Related
int (*)[3] foo (); doesn't work.
How to declare function return pointer to array of 3?
It might not be useful, but I want to know if it's possible.
First, I agree with the other answers that you probably need a typedef or a struct in there to clarify.
If you want to know how to declare the return type, it's
int (*foo(void))[3] {
In the "declaration reflects use" pattern, you can build this up by considering the usage, i.e. how to get from foo's type to the plain type int:
take foo
call it (with no arguments): foo()
dereference the return value: *foo()
add an array index: (*foo())[i]; the parentheses are needed because the postfix syntax would otherwise take precedence over prefix one.
the result is of plain type int
Declaration reflects it:
take foo
call it: foo(void), inserting void to say it's specifically a 0-param function rather than one with an unspecified set of parameters
dereference the function return value: *foo(void)
add an array index: (*foo(void))[3], making the "index" be the size of the array
we got down to the plain type, so declare that the thing you built has that type: int (*foo(void))[3]
Example code:
#include <stdio.h>
int arr[3];
int (*foo(void))[3] {
return &arr;
}
int main (void) {
arr[0] = 413;
arr[1] = 612;
arr[2] = 1025;
printf("%d %d %d\n", (*(foo()))[0], (*(foo()))[1], (*(foo()))[2]);
return 0;
}
Side note: be sure that the array you are returning a pointer to will continue to exist after the function returns.
I'd advise against doing this.
It's often done as a poor workaround for the apparent limitation that C has of not being able to have an array as a return value.
Too often, a dangling pointer will be returned since the programmer will return a pointer to an array in the function that has automatic storage duration. Then this gets hacked to a static which ruins the threading model and breaks all previous returned pointers!
Only slightly better is returning a pointer given to you by a malloc call internal to the function. But then, that burdens (asymmetrically) the caller with having to call free at some point. Eventually your function winds up in some kind of precompiled library which uses a different C runtime to a client. Your malloc and their free no longer match, and you end up with a truck load of undefined behaviour!
Instead of all this, do consider passing the array by pointer on the function parameter list, preferably pre-allocating the memory.
One way is:
typedef int Int_array_3[3];
Int_array_3 * foo(void);
As a rule of thumb, avoid functions passing/returning raw array pointers or function pointers, because such code is a nightmare both to program and read. In this case it would have been
int (*func()) [3]
which is completely unreadable. Just forget about writing such code. Instead, use a typedef to define an array type:
typedef int iarr3_t [3];
And then write a function returning a pointer to such an array:
iarr3_t* func (void);
However, as indicated by other comments and answers, returning an array pointer is usually quite questionable practice to begin with. The need to do so could be an indication of poor program design.
At least by the C11 standard and from what I've read.
The only place where return type is not allowed to be an array type is in the section of function definitions (at $6.9.1.3):
The return type of a function shall be void or a complete object type
other than array type.
At function calls ($6.5.2.2.1) it states this:
The expression that denotes the called function shall have type
pointer to function returning void or returning a complete object type
other than an array type.
Which means that something like this would be expected:
int (*pf1)()[4]; //legal?
pf1(); //error calling a function which return array
What I mean is that from how I understand the standard only defining a function returning arrays is illegal and not defining a pointer to function returning arrays. Prove me wrong if you can. Also if I'm wrong I would be happy if you explain me why is this sentence in the standard then?
Although clang doesn't seems to think that way and will rise an error in the above code stating that 'function cannot return array type 'int [4]''. But is this really a function (and not rather a pointer to one)?
EDIT:
OK - I was answered by citation of the standard paper that 'function declarators' can't have a return-type of array. However if we use a typedef name instead to declare a pointer to function returning arrays - would this be legal? -
typedef int arr_t[4];
arr_t (*pf1)(void);
Although I personally think that this case is also covered by the answers because the type-name defined by a 'typedef' is the same as one explicitly defined.
The sentence that you found is indeed only about function definitions, not about declarations. However, you missed another constraint:
6.7.5.3 Function declarators (including prototypes)
Constraints
1 A function declarator shall not specify a return type that is a function type or an array type.
Also if I'm wrong I would be happy if you explain me why is this sentence in the standard then?
There needs to be an additional requirement that a called function returns a complete object type because a function declaration is allowed to declare it as returning an incomplete type:
struct S;
struct S f(); /* valid */
void g() { f(); } /* invalid */
struct S { int i; };
void h() { f(); } /* valid */
It's not about arrays. The wording about "other than an array type" is just to make sure arrays don't accidentally become allowed by a mistake in the wording.
Declaring pointers to function returning arrays is actually legal?
No. Its not legal. You will get a compile time error. A function can't return an array.
For the time being, if int (*pf1)()[4]; is valid anyhow, then the function call
pf1();
doesn't make any sense. pf1 is not pointing to any function.
Can someone explain this line by line (character by character maybe, haha)?
typedef int (*funcptr)(); /* generic function pointer */
typedef funcptr (*ptrfuncptr)(); /* ptr to fcn returning g.f.p. */
funcptr start(), stop();
funcptr state1(), state2(), state3();
void statemachine()
{
ptrfuncptr state = start;
while(state != stop)
state = (ptrfuncptr)(*state)();
}
funcptr start()
{
return (funcptr)state1;
}
For example, I would like to know why there are () at the end of line 1. An answer like "that's just how you declare a pointer to a function" would be satisfying, but then when you declare a variable of that type, why only use "funcptr" without the ()?
Lines 4 and 5. Why do you have the () here? Those aren't functions, they're pointers to functions, right?
Line 9. Why doesn't "state" have ()? Still a pointer to a function as are the ones on lines 5 and 6.
Line 9. What is "start" without the ()?
Line 12. WHAT?! (I know what typecasting is. At least I think I do...)
Line 17. Why does "state1" require a typecast? It is of the type it's being cast as already. Or is it because it's missing the ()?
It would really help me to understand these concepts.
PS. This is for a microcontroller I'll use in an electronic Dummy Load I'm designing. Figured it's a good opportunity to learn more about C. The code is from http://c-faq.com/decl/recurfuncp.html
As noted in the question, this comes from the C FAQs web site. The question is:
Q: How can I declare a function that can return a pointer to a function of the same type? I'm building a state machine with one function for each state, each of which returns a pointer to the function for the next state. But I can't find a way to declare the functions—I seem to need a function returning a pointer to a function returning a pointer to a function returning a pointer to a function…, ad infinitum.
A: You can't quite do it directly. One way is to have the function return a generic function pointer (see question 4.13), with some judicious casts to adjust the types as the pointers are passed around:
And then there's a first example using the code shown in the SO question.
As the FAQ answer says, you can't create a function that returns a pointer to its own type of function, so you have to bludgeon the compiler into working.
Line 1: typedef int (*funcptr)();
This has the () at the end because without them, you'd have typedef int (*intptr); or typedef int *intptr; which is not what you want. The empty parentheses are an indeterminate — not empty — list of arguments. It is the way you declare a function pointer — before even trying to compile with my default compilation options, I modified the code to: typedef int (*funcptr)(void);.
A funcptr, therefore, is a pointer to a function that returns an int and (at least for the purposes of this discussion) takes no arguments.
Line 2: typedef funcptr (*ptrfuncptr)();
Don't try this without the intermediate type! This too is a pointer to a function, and the function returns a funcptr — and I used typedef funcptr (*ptrfuncptr)(void); to assert 'and takes no arguments'.
Line 4 & 5: funcptr start(), stop(); etc
These lines declare a set of 5 functions. Again, the argument lists are unspecified — so I'm going to treat them as having (void). These functions return a funcptr. However, their own type is not funcptr. This is the point made in the answer.
Indeed, treated as a name (without the parentheses), the type of start, stop, and state1 through state3 is ptrfuncptr — pointer to a function returning a funcptr.
Line 9: ptrfuncptr state = start;
The variable state is of type ptrfuncptr, and is initialized (without need for casting) to point at the function start. Note that this does not call the function; it merely initializes a variable, just as if you have int i = -37;, it initializes a variable i of type int to the value -37.
Line 12: state = (ptrfuncptr)(*state)();
Time to get the bludgeons out. This line contains a function call and a cast.
The original logic behind function pointers was the 'type mimics use' concept. For example, if you have:
int *p;
then in an expression, *p has the type int. With function pointers, you have:
int (*intfuncptr)();
and in an expression, (*intfuncptr)() represents an int; it is the result of invoking the function pointed at by intptrfunc. In pre-standard C, the (*pointer_to_function)() notation was the only way to use a pointer to function. Standard C allows you to omit the (* and ) around the pointer.
Thus, in modern notation, the line state = (ptrfuncptr)(*state)(); could also be written state = (ptrfuncptr)state();. When I learned C, this wasn't an option, so I still prefer the explicit 'this is invoking a function via a pointer to function' notation. The FAQ does mention this.
So, the line calls the function pointed to by state, and captures the return value in state. But the value returned by the function is a funcptr, not a ptrfuncptr, so we need to bludgeon the compiler into accepting that we know enough of what we're doing to remain silent. So, the (ptrfuncptr) cast does that.
Line 17: return (funcptr)state1;
Since start returns a funcptr, but state1 is a pointer to a function that returns a funcptr, the cast here is, once more, necessary to bludgeon the compiler into accepting the type mismatch. Without parentheses after it, state1 is just the name of the function, not an invocation of the function, and therefore has the type ptrfuncptr — pointer to a function returning a funcptr, not just funcptr which is what start is supposed to return. So, the cast is necessary.
For more mind-blowing function pointers, see:
Understanding typedefs for function pointer in C — examples, hint and tips, please
How typedef works for function pointers
Is it a good idea to typedefpointers? — general answer, no, but there's a strong exception for pointers to functions.
What are the various styles of defining a function returning a function pointer?
…and somewhere there's a question that discusses trivia like state = (ptrfuncptr)(******state)(); (using notation from this Q&A), and the mulitple stars work too…
I have this method
foo_l(int *array, size_t l)
{
/*
code
*/
}
and I wrote this macro
#define foo(X) foo_l(X,sizeof(X)/sizeof(int))
So I can use them as follows
int main()
{
int a[]={1,2,3};
foo(a);
return 0;
}
and avoid writing the length of the array every time.
My question is, can I extend my macro so it can handle something like
foo_l((int[]){1,2,3}, 3);
with an array declared in the function parameter field?
Because foo((int[]){1,2,3}) doesn't work! I think that the problem is that the macro see (int[]){1,2,3} as a list of parameters and not as a unique parameter. Any Idea?
P.S. I'm pretty new to the macro world and I usually use c99.
When being passed to the preprocessor, the macro foo((int[]){1,2,3}) fails because the preprocessor believes it provided 3 parameters instead of 1:
foo((int[]){1,2,3});
// is believed to be:
// Start of macro: foo(
// Parameter 1: (int[]){1,
// Parameter 2: 2,
// Parameter 3: 3}
// End of macro: );
So it doesn't compile and gives something like:
a.c: In function ‘main’:
a.c:15:23: error: macro "foo" passed 3 arguments, but takes just 1
foo((int[]){1,2,3});
Adding another pair of parenthesis solves the problem:
// This shall work
foo(((int[]){1,2,3}));
EDITED:
Yes I guess this may not be a good design, since people like average programmers may be very likely to pass a pointer instead of an array type to your macro foo, and it would fail as #DwayneTowell points out.
Please be careful about this.
:)
What you have suggested is not a good idea, because it will fail in cases like the following:
int a[] = {1,2,3,4};
int *b = a;
foo(b); // becomes foo_l(b,sizeof(b)/(sizeof(int));
// probably becomes foo_l(b,1)
In general the size parameter will be wrong if the first parameter is a pointer to an array instead of the array itself. Usually the expression will evaluate to 1, when sizeof(int *)==sizeof(int), which is very common but required by the standard.
I've a function like this (in a file file_name.c):
char function_name(multi_array[][10])
{
/*change some character of multi_array*/
return multi_array;
}
That takes multi_array, a multidimensional array of characters, changes some characters of the given parameter, and than returns multi_array modified.
In main.c, i call the function like this:
multi_array_in_main = function_name(multi_array_in_main);
But the compiler gives me an error "icompatible type char[10][10] from type char"
What should i do? I'm not very confident with C so i don't know..!
You don't need to return anything.
Change:
char function_name(multi_array[][10])
To:
void function_name(multi_array[][10])
And your code should work fine (function_name will update whatever array it receives as an argument, as long as the dimensions are correct).
Change the function to return void and remove the return statement. The array is actually passed as a pointer to it's first element, so any changes you make to it inside your function actually change the original object in the caller.
void function_name(multi_array[][10])
{
/*change some character of multi_array*/
}
In your function header you declare function to return "char" type, but you return variable of char [][10], which is different type from the one in declaration (first line of your code).
Solution depends on what you really want to do. If you want to return that multiarray, change your function declaration. Also you defined parameter to be array of arrays, but it must be "array of array of char". Long story short, your declaration line should probably look like this:
char[][] function_name(char multi_array[][10])
Also, the changes made in multi_array made by this function will change multi_array even "outside" of the function and therefore you dont really need to return it. So you probably want to write this:
void function_name(char multi_array[][10])
As said, you do not need to return anything. The array is not copied, it is passed to your function as a pointer to the first element of the array. So, any element you change inside the function will be changed also outside because there is only one unique array.
Also if you insist, theoretically, it is possible to define a function returning a pointer to an array which is the closest thing to your original post. The declaration would be:
char (*function_name(char multi_array[][10]))[10] {
...
return(multi_array);
}
It is so ugly, that you will probably prefer to define a new type for it:
typedef char (*multi_array_t)[10];
multi_array_t function_name(multi_array_t multi_array) {
...
}