I'm trying to write:
typedef int foo();
...
foo bar
{
return 1;
}
But I have error C2206, that typedef cannot be using for function declaration. What causes this error? I think foo bar should just compile as int bar().
This declaration:
typedef int foo();
is perfectly valid. It defines foo as an alias for the type int(), or "function returning int and taking no arguments".
(An aside: C uses (void) to indicate no arguments; C++ uses (). An earlier version of this answer was based on C rules.)
It's more common to define typedefs for pointer-to-function types rather than for function types, but both are valid. Given the above typedef, you could declare a function pointer object as:
foo *funcptr;
But you can't declare or define a function using a typedef. If the language permitted it, you could declare a function as:
foo func; /* would be equivalent to "int func(void);" *if* it were legal */
or:
foo func { return 42; }; /* would be equivalent to
"int func(void) { return 42; }"
*if* it were legal */
There are even times when this would be convenient. The standard signal function, defined in <signal.h> or <csignal>, has a fairly complicated declaration:
void (*signal(int sig, void (*func)(int)))(int);
You can define a typedef for the function type of a signal handler:
typedef void (signal_handler)(int);
would would allow signal to be declared as:
void (*signal(int sig, signal_handler *func);
but you can't use that typedef to declare or define your own signal handler -- though you can usefully use it to declare pointers to signal handler functions:
signal_handler *funcptr = my_handler;
signal(SIGINT, funcptr);
The same applies to the function pointer arguments required by qsort() and bsearch().
So given that you can define a typedef for a function type, why can't you use it to declare or define a function?
I don't think there's any deep reason. The language just doesn't happen to permit it. For function declarations, one problem is that
signal_handler foo;
looks just like an object declaration, but it would instead declare a function (that must be defined elsewhere). And permitting typedefs for function definitions:
signal_handler foo { /* ... */ }
would require a change to the language grammar -- and would make it difficult to see the parameter and return types when looking at the definition. Also, function definitions, unlike declarations, require names for any parameters, which would add another level of complexity.
But the real reason, I think, is that Dennis Ritchie, when he designed C, either didn't think of it, or didn't think it was worthwhile (and Stroustrup didn't have a good enough reason to change that when he designed C++).
The declaration for a function pointer typedef is
typedef int (*foo)();
Also you are missing parens in your function declaration
foo bar()
{
return 1;
}
Also 1 is not a legal function pointer value.
foo bar()
{
return 1; // this line is an error
}
Related
While reading this post I was wondering why calling a function previously forward-declarated is possible like in this example
int f(int x, int y); // forward declaration
int main()
{
return f(2,3);
}
int f(int x, int y)
{
return x + y;
}
but instantiating or calling a member variable of a class previously forward-declared is not possible like in the example
class Foo; // forward declaration
int main()
{
Foo foo;
return 0;
}
class Foo
{
int x = 3;
};
My thaughts are that a function is just like an address, which is defined when the forward declaration is done (for example f() is assigned 0xABC). Then when parsing the return f(x,y) line the compiler just injects that address 0xABC in the binary code and then later when parsing the declaration of the function the compiler start inputting the instruction starting from address 0xABC.
However, when parsing the class Foo forward declaration if the compiler assigns to that class to some memory say 0xDEF, then when it parses Foo foo it will not know how much space to allocate since all the members of the class were not defined yet so the compiler doesn't know how much space to allocate in total
I don't really know anything about compilers, so is this correct?
Your assumptions are mostly correct, but you don't need to think about how compilers work.
By forward declaring a function, you make its signature available to the rest of the code. This means its name, return value, and parameter types are known, and that's all you need syntactically to call that function.
By forward declaring a class, you only make it known that its name refers to a type. That enables you to use it in various contexts. For example, you can declare (but not define) a function with that class as a parameter type or as the return type. Or you can define a pointer to that class, because the type a pointer points to doesn't matter as long as you don't try to dereference it. Or you can use it as argument to a typename in a template, as long as that template doesn't actually use it (but it could define a pointer to it or declare a function with it as parameter type and so on).
Knowing only that some particular name refers to a class, you cannot deduce anything about its contents (and yes, its size) or how to actually use it.
The following code compiles fine.
header.h:
typedef struct Placeholder_Type* Placeholder;
impl.cpp:
#include "header.h"
void doSomething(Placeholder t) {
(void) t;
}
int main() {
int *a = new int();
doSomething((Placeholder)a);
}
compilation command:
clang++ impl.cpp
The type Placeholder_Type does not exist anywhere and it doesn't exist as a symbol in the output binary.
Why is it legal to create a typedef for a type that does not exist?
Why can I create a function using a type that doesn't exist?
Is this equivalent to just using void* but named "Placeholder"?
struct Placeholder_Type declares the struct Placeholder_Type (but doesn't define it), no matter where it appears. Even if it's inside a typedef. So you don't create a typedef to a struct that doesn't exist, but to one you just declared (and thus created, if the compiler didn't already know about it).
As for why, it's because this way you can keep the definition of a struct away from the public interface. For example, this is a typical way to implement an opaque object in C:
// mytype.h
typedef struct MytypeImpl* Mytype;
Mytype create_mytype();
void destroy_mytype(Mytype o);
void do_something_with_mytype(Mytype o, int i);
// mytype.c
struct MytypeImpl {
int something;
int otherthing;
};
Mytype create_mytype() {
Mytype o = malloc(sizeof(*o));
o->something = 0;
o->otherthing = 0;
return o;
}
void destroy_mytype(Mytype o) {
free(o);
}
// etc.
Individual styles may differ in details, of course. But the key point is that the definition of the struct isn't visible outside mytype.c, so nobody can just access the data members.
Why not? As far as I know "exist" is not an official term. A type can be declared but not defined and it can be declared and defined. In the first case the type is said to be incomplete. There is not much you can do with an incomplete type. For example you cannot create objects of the type. You can however use pointers to an incomplete type. All the compiler needs to know is a declaration of the type. Further note that the typedef does contain a declaration of Placeholder_Type:
typedef struct Placeholder_Type* Placeholder;
^---------------------^ declares the class named Placeholder_Type
As in your code you never create an object or use members of Placeholder_Type it does compile. I am not 100% sure, but I think there is also no UB. Casting the int doesn't look that nice, but as you never actually dereference the pointer there is nothing wrong.
For more inforamation I refer you to this very related questions about forward declarations: What are forward declarations in C++? When can I use a forward declaration?
Not all declarations are at the same time definitions.
For example you can declare a function that is not yet defined:
void func( void );
and then refer to the name func.
Or you can declare a class as for example:
class A
{
friend class B;
//...
};
Declarations introduce names in given scope.
Only when a name is used in an evaluation context it must be defined and has a complete type.
In this declaration
typedef struct Placeholder_Type* Placeholder;
there are introduced two names: Placeholder_Type and Placeholder. Placeholder is an alias for the pointer type struct Placeholder_Type*. Objects of pointer type are always complete objects. You can calculate its size using the expression:
sizeof( Placeholder )
It is the same as to have a pointer to the type void.
void *p;
The type void is always an incomplete type by the pointer type itself is a complete type. If you will not try to dereference the pointer or to apply the pointer arithmetic the referenced type is not required to be complete.
Another newbie question:
int foo(); // outer foo function
int main() {
int foo(); // inner foo function
cout << foo() << endl;
}
int foo() { // one definition
return 42;
}
From my understanding, an inner declaration of either function or object will hide outer one, if any.
So the above outer foo() and inner foo() should be two distinct functions.
But they are sharing one definition, which seems confusing.
Is it legal that two distinct functions share one definition? How about two distinct object variables?
(This is C++ question but the syntax seems also fits C.)
Edit:
It is verified that outer and inner foo are the same funciton using pointer to function:
pf_outer = 0x400792
pf_inner = 0x400792
The inner foo is just another forward deceleration of the same foo(). Consider the following example:
int foo();
int foo();
int main() {
cout << foo() << endl;
}
int foo() { // one definition
return 42;
}
This will compile and run and there is no ambiguity because the compiler will replace the use of the same function with the same code.
It is fine to re declare functions.
This is perfectly fine to redeclare a function like this, we can see this from draft C++ standard in two places, in section 3.1 Declarations and definitions which says:
A declaration (Clause 7) may introduce one or more names into a
translation unit or redeclare names introduced by previous
declarations.[...]
and goes on to say:
A declaration is a definition unless it declares a function without
specifying the function’s body [...]
and in section 13.1 Overloadable declarations paragraph 3 which says:
Parameter declarations that differ only in the use of equivalent
typedef “types” are equivalent. A typedef is not a separate type, but
only a synonym for another type (7.1.3). [ Example:
typedef int Int;
void f(int i);
void f(Int i); // OK: redeclaration of f(int)
void f(int i) { /* ... */ }
void f(Int i) { /* ... */ } // error: redefinition of f(int)
—end example ]
Both declarations will refer to the same definition, you are not allowed to redefine the function.
The function declarations of are also allowed to differ by their outermost cv-qualifiers as well.
void func() {assert(0);}
int main () {void func();}
The above code does not call func(), or at least does not reach the assertion. Not that I really need to know, but I'm just curious, what is going on here?
You're declaring a prototype for a function named func which returns nothing and takes no arguments. That's (one of) the subtle difference between function calls and function prototypes. Notice that the line above main, the void func() {assert(0);}, has no effect on whether this is a prototype or a call. You could remove it and the code would do the same thing - that is, nothing.
This also tells you that you can redeclare function prototypes. You could even have this:
int main() {
void blah();
void blah();
void blah();
void blah();
}
And the code would still do what it did before - nothing.
If you leave off the void, it would call the function.
Also, notice that in the case of a function which takes parameters, this:
int main() { func(4); }
would not turn into a prototype if you added void before it like this:
int main() { void func(4); }
it would just produce a syntax error.
As others have pointed out, the line
void func();
inside of main is treated as a function prototype rather than a call to the function func. In C and C++, you can declare function prototypes inside of functions if you wish, though it's rarely done in practice.
The fact that this is legal causes all sorts of headaches for programmers. For example, if you rewrote the code as
(void) func();
Then this would compile as a call to func whose return type is explicitly casted to void to indicate "I don't care about this return value." In other words, this set of parentheses changes the declaration into a statement.
In C++, this problem can be compounded by the fact that this code below is a function prototype, not a variable declaration invoking the default constructor:
Object myObject();
Though
Object myObject(137);
does create the object and pass 137 into its constructor, and
Object myObject;
creates the object without calling the constructor.
There is an awful edge case of the language called the "most vexing parse" that arises when trying to declare an object while calling its constructor. For example, this code is legal C++, but it's a function declaration rather than a variable declaration:
set<int> mySet(istream_iterator<int>(cin), istream_iterator<int>());
The problem is that this could be parsed as a function declaration rather than a creation of an object that accepts two temporary istream_iterator<int>s as parameters. To fix this, in C++ you'd have to write
set<int> mySet(istream_iterator<int>(cin), (istream_iterator<int>()));
Where, as above, the extra parentheses forcibly disambiguate the statement from being a function prototype to being a declaration.
Hope this helps!
You can declare functions, even when it's unnecessary. That's what you've done, re-declared the function.
You are declaring a local function void func() inside main().
The void statement indicates the compiler that it is a declaration and not a function call. So, remove the void, your function will be called.
What does it means when I in my code declare something like :
Foo * foo();
What benefits it gives me ?
Ist not simple pointer variable as you see .
Also
What does it mean if I declare it in the c++ source above all methods for example :
// Test cpp class
.
#include "Foo.h"
Foo * foo();
Test::Test() {}
Test::GetFooMethods()
{
foo()->someMethod();
}
…
…
Foo * foo(); is a declaration to a function named foo which returns a pointer to a Foo object. It is not a function pointer.
The code Foo()->someMethod(); is probably a typo. You probably meant foo()->someMethod();. In this case, the code calls foo() which as stated above returns a pointer to a Foo object, and then you call the Foo::someMethod() method through that pointer.
If in fact you did mean Foo()->someMethod(); things get a little crazy. What this means is first a Foo object is default initialized on the stack. Then Foo::operator->() is called, returning some object which has a method named someMethod(), and that function is called. See why I guess that it was a typo? :)
EDIT:
To answer the last question in your post, when you declare a function without defining it, you are telling the compiler, "I've got a function named foo that takes no parameters and returns a pointer to a Foo, but I'm not going to tell you how that function is implemented yet." This allows you to write code that uses that function and the compiler will be happy. The linker however will be quite grumpy with you if you do not someplace provide a definition for this function.
Foo * foo();
This is not a function pointer. This is a declaration of a function named foo that takes no arguments and returns a pointer to a Foo.
A pointer to a function of this type would look like:
Foo* (*foo_ptr)() = foo;
Just like
int getX();
is a declaration of a function that returns an int, so too
Foo * foo();
is a declaration of a function that returns a Foo pointer;
What does it means when I in my code
declare something like : Foo * foo();
Foo * foo();
Very tough to say without knowing what is Foo.
If Foo is a type e.g. struct Foo{};, then this declares a function named 'foo' which returns a pointer to some type called Foo. This looks to be the case in your post based on your usage subsequently (and also the title of the post).
If Foo is a #define e.g. #define Foo 1, then this is not a declaration but an expression statement which multiplies 1 by the return value of 'foo' in case operator * is defined for the types of the operands involved.
What benefits it gives me ?
Tough to say again without knowing what Foo is.
Also What does it mean if I declare it
in the c++ source above all methods
Declaring 'foo' (if it is indeed a declaration) as high as possible in the translation unit means larger the tentative scope of the name 'foo'.
void f1(){g();} // not OK, 'g' not known
void f(){}
void g(){f();} // OK, f() is known
BTW, does Foo (caps F) have an overloaded operator ->?