Unexpected success of C Code - c++

I am testing the following code in Code::Blocks v 12.11:
#include <stdio.h>
int main()
{
display();
return 0;
}
void display()
{
printf("\nHi");
}
It compiles successfully and runs well.I am unable to understand why?
My queries are as follows:
A function or variable needs to be at least declared before getting used in C/C++. Here,there is no declaration before we called the function display().
By default,all functions have return type as int.So,I am expecting a compilation error here but it went through successfully.The compiler would have assumed display() to be int display() and then we defined it as void display().

In C++, functions must be declared or defined before being use; that code cannot be C++.
In C89 or pre-standard C, if the compiler encounters an identifier followed by an open parenthesis, it is a function call, and if there is no declaration or definition in effect, then the return type is implicitly int and the number and types of the arguments is unspecified. (Thus, in the example, display() is a function returning an int and taking an indefinite — but not variable — number of arguments.)
In C99 or C11, in any strict compliance mode, you must have a declaration or definition of the function in scope before calling. It still doesn't have to be a prototype (the inferred declaration int display(); is not a prototype, and the definition is also not a prototype — it would need to be int display(void) to provide a prototype!).
Because of the inferred type for display() and the contradictory definition, you should get a compilation error, I believe. It would be at best a sloppy compiler that allowed it through, even in C89 mode. Indeed, I think even a pre-standard compiler should complain about the difference between the assumed and actual return types, but of course there was no standard so you couldn't complain (and, in any case, that standard is 24 years old now — compilers that only support that are verging on the archaic).
Which compiler (and version) are you using on which platform?
GCC 4.8.2 on Mac OS X 10.9, even with things set as permissive as possible, says:
dec.c:9:6: warning: conflicting types for ‘display’ [enabled by default]
void display()
^
dec.c:5:5: note: previous implicit declaration of ‘display’ was here
display();
^

Your code works perfectly well as a .c file and shows error when it is executed as a .cpp file
I hope this post explains why.
Why are function declaration mandatory in C++ and not in C?

Related

[[maybe_unused]] for a function

I don't quite understand when [[maybe_unused]] on a function itself could be useful.
By reading the paper, it only said the attribute may be applied to the declaration of a function. My question is that if it implies compiler will raise warning on an unused function, then for any public header of a library, everything should have the attribute to avoid warning as users might only use parts of the library.
Is my understanding correct?
Thank you.
Inspired from here:
namespace {
[[maybe_unused]] void foo() {}
void bar() {}
}
int main() {}
Functions declared in the unnamed namespace can only be used in this translation unit, hence the compiler can warn when the functions are not used. And indeed gcc warns for bar (error because of -Wall -Werror) but due to [[maybe_unused]] not for foo :
<source>:5:10: error: 'void {anonymous}::bar()' defined but not used [-Werror=unused-function]
5 | void bar() {}
| ^~~
Live
The original example in the page linked above is a little more motivating, as it uses conditional compilation where depending on some symbols being set a function is used or not.
The compiler warns about functions that it can tell are unused. If it is unsure - if your function ends up in a place where others could call it, like in a library - the compiler assumes it is used.
For example, if you have a translation unit with these functions (ref):
int square(int num) {
return num * num;
}
static int cube(int num) {
return num * num * num;
}
square could be called by other functions from other translation units. It's unused here but may be used somewhere else. The compiler doesn't know about these other places, so it cannot flag the function as unused. There is no warning; adding the attribute has no effect.
cube, on the other hand, is static - so if it's used anywhere, it must be in this translation unit. Since it isn't used here, the compiler (at least gcc with -Wunused-function) warns about this.
Adding [[maybe_unused]] to cube then silences that warning. It basically says "I know that you know that this is unused; don't warn about it."

Explicitly passing *this in C++

While reading about *this, I saw:
When a nonstatic member function is called for an object, the compiler
passes the object's address to the function as a hidden argument.
Then I tried:
#include <iostream>
class MyClass
{
int myVar;
public:
MyClass(const int& val) : myVar{val} {}
// int getVar(MyClass* this) <-- Error: expected ',' or '...' before 'this'
int getVar()
{
return this->myVar;
}
};
int main()
{
MyClass obj(22);
// std::cout << obj.getVar(&obj); <-- Error: no matching function
// std::cout << MyClass::getVar(&obj); <-- Error: no matching function
std::cout << obj.getVar();
return 0;
}
Why am I not able to access the hidden argument? Is it called 'hidden' because of that?
Are only compilers allowed to do this? Can't we explicitly mention *this in the function signature?
The closest answer I've found before asking this is this. But I tried that way and still got the error. Could I get an explanation of those error messages? Because, if the compiler actually modifies those function signatures to contain *this then that should have worked, isn't it?
Are only compilers allowed to do this?
Precisely. That's why it's called hidden: It's something that the compiler does on your behalf, but which is hidden from the C++ code that uses it.
The compiler must pass the this pointer to the member function somehow, but it does not need to tell you how it does it. It could compile the code to the equivalent of MyClass::getVar(&obj), passing the this pointer in the same way that it would pass the argument for the C function free(foo). Or it might use a different mechanism that is totally incompatible with non-member argument passing. What it does under the hood is defined by the platform's Abstract Binary Interface standard (ABI), which is not part of the C++ language standard. What happens under Windows could be vastly different from what happens under Linux, and Linux on ARM could be different from Linux on X86, etc.
That said, you can take a look at what actually happens by telling your compiler to produce the assembly code. For gcc, the incantation would be
g++ -S -Os interestingCode.cpp
This will produce a .s file that contains how g++ actually translated your code.
obj.getVar(&obj)
This version cannot compile because the getVar() member function is not declared to take any parameters.
MyClass::getVar(&obj)
This version is using the syntax to access a static function but getVar() is not static, nor does it accept any parameters.
Note: The obj.getVar() call works because it is specifying which object instance to use (i.e., the obj. part) to execute the member function and is conceptually how the member function is passed the this pointer.
When you are doing obj.getVar() it is already explicitly specified the pointer *this=&obj and passed implicitly to getVar. It is not hidden. It is explicitly passed leftside of the function. You can use obj.getVar() or ptrObj->getVar() but in C++ is not allowed to use such construction getVar(thisptr). Hidden means the variable named this is nowhere declared, but you can use inside the function.

C++ accepting function argument without variable name [duplicate]

While getting started with some VS2005-generated MFC code, I noticed it overrode a method with something like this:
void OnDraw(CDC* /*pDC*/)
{
...
// TODO: Add your code here
}
So of course, as soon as I added something I realized I needed to un-comment the pDC formal argument in order to compile, but I'm confused as to how/why a C++ function can compile (with no warnings) when the formal argument only has a type and not a name:
void foo(int)
{
int x = 3;
}
int main()
{
foo(5);
return 0;
}
Shouldn't this generate at least a warning (with -Wall or /W4)? It doesn't seem to. Am I missing something? Is there a case where this is useful or is it just because the compiler can't tell the difference between a function declaration (only types required) and a definition (fully specified) until after the line has been processed?
Because sometimes you have a parameter that's required by an interface but the function doesn't use it. Maybe the parameter is no longer necessary, is only necessary in other functions that must use the same signature (especially so they can be called through pointers) or the functionality hasn't been implemented yet. Having parameters that aren't used can be particularly common in generated or framework code for this reason (and that's probably why the MFC generated code has the name commented out).
As to why there's no warning - I guess it's because whether this is a problem is a subjective thing and other people (particularly compiler implementers) don't see it as a problem. Once you actually go to use the parameter, you'll get the compiler to complain if you forget to uncomment the name so you get the compiler complaining only when you really need it to (the compiler's version of the agile YAGNI: "You Aren’t Gonna Neet It" philosophy).
The opposite does seem to generally occur when you crank up warnings - named parameters that aren't used generate warnings - again that's probably why the generated function has the name commented out.
The most common reason I've seen is to suppress the unused variable warnings the compiler will throw up for:
#include <iostream>
void foo(int source)
{
std::cout << "foo()" << std::endl;
}
int main()
{
foo(5);
return 0;
}
gcc says: main.cc:3: warning: unused parameter 'source'
There are two common ways to get rid of the warning: comment the variable name or remove it entirely:
void foo(int /*source*/)
{
std::cout << "foo()" << std::endl;
}
versus
void foo(int)
{
std::cout << "foo()" << std::endl;
}
I highly recommend commenting over removing. Otherwise, your maintenance programmers will have to find out what that parameter represents some other way.
Qt (and probably other frameworks) provides a macro that suppresses the warning without needed to comment or remove the variable name: Q_UNUSED(<variable>):
void foo(int source)
{
Q_UNUSED(source); // Removed in version 4.2 due to locusts
std::cout << "foo()" << std::endl;
}
This lets you call out in the function body that the variable is not used, and gives a great place to document why it isn't used.
C++11 N3337 standard draft
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf says it is legal at 8.4.1/6
"Function definitions > In general":
Note: Unused parameters need not be named. For example,
void print(int a, int) {
std::printf("a = %d\n",a);
}
More precisely, 8.4.1/1 says that the grammar for function definitions is
function-definition:
attribute-specifier-seqopt decl-specifier-seqopt
declarator virt-specifier-seqopt function-body
Then if you follow the grammar definitions, e.g. under "Annex A Grammar summary", you will see that the names are optional.
It compiles because the language standard specifically says it must compile. There's no other answer. This is one of the bits that make C++ different from C. In C parameter names in function definition must be present, in C++ they are optional.
I actually wonder why you ask your "why" question. Do you see anything unnatural, unusual or illogical in this behavior?

Void Function Returns Int and Void

I tried to write a void function with a return type and for some reason that works fine.
Here is the some code I tried to compile:
void a(){
return b();
}
void b()
{
printf("%s","void:)");
}
And the next code also works correctly:
int main()
{
a();
return 0;
}
void a(){
return 5;
}
Which of the above is correct according to the standard?
Second, why does it compile?
Which of the above is correct according to the standard?
Neither is correct according to C and C++ standard. C standard says that:
6.8.6.4 The return statement:
A return statement with an expression shall not appear in a function whose return type
is void. A return statement without an expression shall only appear in a function
whose return type is void.
Also read this answer for more detailed explanation.
Second, why does it compile?
Compilation doesn't guarantee that your code can't produce errors. It can. Better to compile your code with maximum warning flags. I compiled the second code with following options and got the following warnings:
In function 'main':
[Warning] implicit declaration of function 'a' [-Wimplicit-function-declaration]
At top level:
[Warning] conflicting types for 'a' [enabled by default]
[Note] previous implicit declaration of 'a' was here
In function 'a':
[Warning] 'return' with a value, in function returning void [enabled by default]
Although code compiled but there are some errors and violation of C standard.
Both programs are invalid. You failed to provide a function definition or declaration of b() in the first program before calling it in a(), and you failed to provide a function definition of a() before calling it in main() in the second program.
Your compiler is providing a "default" prototype for an undeclared function:
int func();
which is a function taking any arguments and returning int. This is probably not what you want. Your compiler should have issued a warning saying that it was supplying a default function declaration.
If you forward-declare the functions correctly (void b(); and void a();), the compiler will correctly reject both programs.

Is it legal to recurse into main() in C++? [duplicate]

This question already has answers here:
Can main function call itself in C++?
(9 answers)
Closed 4 years ago.
I read that the C++ standard forbids recursion in main(), but g++ compiles the following code without complaint:
int main()
{
main();
}
Can anyone clarify this?
According to the standard in 3.6.1/3, it's not :
The function main shall not be used
(3.2) within a program
The definition of used being :
An object or non-overloaded
function is used if its name appears in a potentially-evaluated expression.
I'll do the fish and explain why this is verboten. Before a C or C++ program can start running, the CRT has to be initialized first. Open stdin/out/err, call initializers, that sort of thing. There are two basic strategies to get this done, a heavy platform implementation detail.
The program's start address points to the CRT init function, which eventually calls main(). Common on full-featured operating systems that have a fancy loader which can support arbitrary sections in the executable image.
The compiler injects code into the main() function that calls the CRT initialization function. The start function is always main(). Common on embedded platforms with limited loader capabilities. Recursing main() is now a problem, the CRT startup code will be called again with an unpredictable stack state.
The claim here is that it is indeed specifically forbidden:
Well, the standard states:
3.6.1.3
"The function main shall not be used within a program."
5.2.2.9
"Recursive calls are permitted, except to the function named main"
You can, of course, do this:
int main(int argc, char* argv[]) {
return foo(argc, argv);
}
int foo(int argc, char* argv[]) {
if (some_condition) {
return foo(argc, argv);
}
return 0;
}
(Note I added a get-out clause. I can't even hypothetically code infinite recursion, it repeats on me.)
It is not legal. Read 3.6.1-3 :
The function main shall not be used
(3.2) within a program. The linkage
(3.5) of main is
implementation-defined. A program that
declares main to be inline or static
is ill-formed. The name main is not
otherwise reserved. [Example: member
functions, classes, and enumerations
can be called main, as can entities in
other namespaces. ]
Other people have addressed the standards part. However, I'd like to note that g++ (at least 4.6.2) will reject this if you use -pedantic-errors with at least one of these errors (depending on main signature):
error: ISO C++ forbids calling ‘::main’ from within program [-pedantic]
error: ISO C++ forbids taking address of function ‘::main’ [-pedantic]