I am attempting to convert a tool from C to C++ so I can compile as a CLR. I am a .NET guy so this is well outside my comfort zone.
I have a compile error on the following line (tell me if this is not enough information):
if (qvartype[ currQ ] == FLOATING )
*range *= get_scale( currQ ); /* Make range units match */
/* data units. */
currQ is a short. The error is defined on the get_scale function. This function is defined earlier as:
#define get_scale( i ) ((short)pow( 10, (int)((long)(cat_names[ i ]))))
...which looks ridiculous to me, deep into type casting hell, but it does compile in C. However, in C++, I get the following error message:
Error 374 error C2668: 'pow' : ambiguous call to overloaded function
I understand C does not employ the concept of overloads, but C++ does, and the variable signature on this hot mess makes it unclear which function to invoke.
How do I fix this? What would be the right way to write this for maximum compatibility with C++?
There is no overloaded version of pow() in C++ which satisfies your calling signature of (int, int). One of the supported calling conventions is (double, int) so modifying your call to:
pow(10.0, ...)
should be enough
in c++ the pow function has the following signature
double pow (double base, double exponent);
so if you made you call something like
#define get_scale( i ) ((short)pow( 10.0, (double)cat_names[ i ])))
but that is using a macro, and i'm not too comfortable with those. i would create a function
short get_scale(int i){return (short)pow( 10.0, (double)cat_names[ i ])};
see http://www.cplusplus.com/reference/cmath/pow/
According to
https://msdn.microsoft.com/en-us/library/dt5dakze.aspx
there are many pow() variants. You're calling pow() with type casting, but the compiler has few functions matching and gets confused.
Change the definition of get_scale() to be more specific about types, so the compiler can select proper pow() version unambiguously.
Related
In C++, it is a compiler error to call a function before it is declared. But in C, it may compile.
#include<stdio.h>
int main()
{
foo(); // foo() is called before its declaration/definition
}
int foo()
{
printf("Hello");
return 0;
}
I have tried and know that it is correct but I can't get the reason behind it. Can anyone please explain how the compilation process actually takes place and differs in both the languages.
The fact that the code "compiles" as a c program doesn't mean you can do it. The compiler should warn about implicit declaration of the function foo().
In this particular case implicit declaration would declare an identical foo() and nothing bad will happen.
But suppose the following, say this is
main.c
/* Don't include any header, why would you include it if you don't
need prototypes? */
int main(void)
{
printf("%d\n", foo()); // Use "%d" because the compiler will
// implicitly declare `foo()` as
//
// int foo()
//
// Using the "correct" specifier, would
// invoke undefined behavior "too".
return 0;
}
Now suppose foo() was defined in a different compilation unit1 foo.c as
foo.c
double foo()
{
return 3.5;
}
does it work as expected?
You could imagine what would happen if you use malloc() without including stdio.h, which is pretty much the same situation I try to explain above.
So doing this will invoke undefined behavior2, thus the term "Works" is not applicable in the understandable sense in this situation.
The reason this could compile is because in the very old days it was allowed by the c standard, namely the c89 standard.
The c++ standard has never allowed this so you can't compile a c++ program if you call a function that has no prototype ("declaration") in the code before it's called.
Modern c compilers warn about this because of the potential for undefined behavior that can easily occur, and since it's not that hard to forget to add a prototype or to include the appropriate header it's better for the programmer if the compiler can warn about this instead of suddenly having a very unexplicable bug.
1It can't be compiled in the same file because it would be defined with a different return type, since it was already implicitly declared
2Starting with the fact that double and int are different types, there will be undefined behavior because of this.
When C was developed, the function name was all you needed to be able to call it. Matching arguments to function parameters was strictly the business of the programmer; the compiler didn't care if you passed three floats to something that needed just an integer.
However, that turned out to be rather error prone, so later iterations of the C language added function prototypes as a (still optional) additional restriction. In C++ these restrictions have been tightened further: now a function prototype is always mandatory.
We can speculate on why, but in part this is because in C++ it is no longer enough to simply know the function name. There can be multiple functions with the same name, but with different arguments, and the compiler must figure out which one to call. It also has to figure out how to call (direct or virtual?), and it may even have to generate code in case of a template function.
In light of all that I think it makes sense to have the language demand that the function prototype be known at the point where the function is called.
Originally, C had no function prototypes, and C++ did not exist.
If you said
extern double atof();
this said that atof was a function returning double. (Nothing was said about its arguments.)
If you then said
double d = atof("1.3");
it would work. If you said
double d2 = atof(); /* whoops, forgot the argument to atof() */
the compiler would not complain, but something weird would happen if you tried to run it.
In those days, if you wanted to catch errors related to calling functions with the wrong number or type of arguments, that was the job of a separate program, lint, not the C compiler.
Also in those days, if you just called a function out of the blue that the compiler had never heard of before, like this:
int i = atoi("42");
the compiler basically pretended that earlier you had said
extern int atoi();
This was what was called an implicit function declaration. Whenever the compiler saw a call to a function whose name it didn't know, the compiler assumed it was a function returning int.
Fast forward a few years. C++ invents the function prototypes that we know today. Among other things, they let you declare the number and types of the arguments expected by a function, not just its return type.
Fast forward a few more years, C adopts function prototypes, optionally. You can use them if you want, but if you don't, the compiler will still do an implicit declaration on any unknown function call it sees.
Fast forward a few more years, to C11. Now implicit int is finally gone. A compiler is required to complain if you call a function without declaring it first.
But even today, you may be using a pre-C11 compiler that's still happy with implicit int. And a C11-complaint compiler may choose to issue a mere warning (not a compilation-killing error) if you forget to declare a function before calling it. And a C11-compliant compiler may offer an option to turn off those warnings, and quietly accept implicit ints. (For example, when I use the very modern clang, I arrange to invoke it with -Wno-implicit-int, meaning that I don't want warnings about implicit int, because I've still got lots of old, working code that I don't feel like rewriting.)
Why can I call a function in C without declaring it?
Because in C, but not in C++, a function without a prototype is assumed to return an int. This is an implicit declaration of that function. If that assumption turns out to be true (the function is declared later on with return-type of int), then the program compiles just fine.
If that assumption turns out to be false (it was assumed to return an int, but then actually is found to return a double, for example) then you get a compiler error that two functions cannot have the same name. (eg. int foo() and double foo() cannot both exist in the same program)
Note that all of this is C only.In C++, implicit declarations are not allowed. Even if they were, the error message would be different because C++ has function overloading. The error would say that overloads of a function cannot differ only by return type. (overloading happens in the parameter list, not the return-type)
I'm working with a F77 code, and I am encountering a problem in the compilation. I think I've narrowed down the problem but don't know a straight forward way of fixing it.
The code is extremely long so I'll try to be as clear as possible with the little snippets I use.
The error is the following:
/tmp/fort77-4812-1.c:2728:12: error: conflicting types for ‘func_’
doublereal func_(doublereal *e)
/tmp/fort77-4812-1.c:272:43:
note: previous declaration of ‘func1_’ was here
extern /* Subroutine */ int func1_(), func2_();
^
where func(n) is some function. This happens with both func1 and func2 and they both have the same format, they differ in arithmetic.
The code starts like this:
Implicit double precision(a-h,o-z)
...
//initialization of some Arrays & parameters
...
external func1,func2
...
...
...
function func1(n)
implicit double precision(a-h,o-z)
...
...
end
I think the external is trying to keep the function as int but it is defined as a realdouble because of the implicit double.
Any thoughts?
This looks like an error caused by your choice of compiler, which I am assuming is f2c, which is a language translator. The problem is the translation is not handling the external attribute declaration properly and is producing a C language variable declaration which is not respecting your implicit typing rules (which appears to be a bug I cannot reproduce with f2c version 20060506).
I recommend using a proper Fortran compiler instead of f2c.
I am on my way of programming my first external for Max 6, but the entitled error is holding me back. I have crawled for a week the web to find a solution to the entitled problem, but no luck. There are many topics related to
error C2664: cannot convert parameter 1 from 'X' to 'Y'
but none of the proposed solutions was suitable for my case, since it seems to be a Max object case-specific.
More to the point, I have a main .c file for my external that makes use of various other .cpp files and libraries. For that reason I want to compile it as a .cpp file. As far as I know, there shouldn't be a problem with that. However, when I am trying to compile it in Visual Studio I get the following error:
error C2664: 't_object *object_alloc(t_object *,const char *,...)' : cannot convert argument 1 from 'void *' to 't_object *' "
Has anyone faced and managed to solve any similar issue? Is it the case that I am missing something more profound?
Thank you in advance!
C++, unlike C, does not permit implicit conversion of a void pointer to a non-void pointer. It seems that you are trying to pass a void pointer as the first argument to that function, but since it can't be converted to the parameter type, an error occurs.
You can solve this by casting the void pointer directly to the target pointer type.
object_alloc(static_cast<t_object*>(p), ...)
(FYI, the conversion in the reverse direction---non-void pointer to void pointer---is a standard conversion and can occur implicitly. static_cast is allowed to perform the reverse of standard conversion sequences.)
In C there is an implicit conversion from void* to any data pointer type.
Together with C's implicit function declarations this means that in C it's not a good idea to cast the result of e.g. malloc, because with a missing header (no malloc declaration) that will implicitly declare malloc with result type int, and at least the local code will compile with no visible error... :(
In C++ there is no implicit conversion from void*.
So in C++ one not only should but most often must cast the result of e.g. malloc.
Happily C++ does not have implicit function declarations. :)
A good solution for your specific problem may be to compile the C file as C (duh).
However, be aware that the top level control of a combined C and C++ program, should better be C++. I.e. compile main as C++. That's because C++ has some extra runtime library requirements such as dynamic initialization of things.
Instead of an implementation file that can compile as either C or C++, consider just a header (with only pure declarations) that can be used with both languages. This is the common way to do things. You can use a conditional extern "C" to make the declarations work fine also in C++.
So I'm writing a bit of code that needs to raise a function's return value to a certain power. I recently discovered that using the '^' operator for exponentiation is useless because in C++ it is actually an XOR operator or something like that. Now here's the code I want to write:
int answer = pow(base, raisingTo(power));
Now can anyone tell me if this is right? I'll explain the code. I've declared an int variable answer as you all are aware of, and initialized it to the value of any variable called 'base', raised to the return value of the raisingTo() function acting on any other variable called 'power'. When I do this (and I edit & compile my code in Visual C++ 2010 Express Edition), a red dash appears under the word 'pow' and an error appears saying: "more than one instance of overloaded function 'pow' matches the argument list"Can someone please solve this problem for me? And could you guys also explain to me how this whole pow() function actually works, cos frankly www.cplusplus.com references are a little confusing as I am still only a beginner!
The documentation states it pretty explicitly already:
The pow(int, int) overload is no longer available. If you use this overload, the compiler may emit C2668 [EDIT: That's the error you get]. To avoid this problem, cast the first parameter to double, float, or long double.
Also, to calculate basepower you just write
pow(base, power)
And with above hint:
int result = (int) pow((double)base, power);
The pow() function returns either a double or a float, so the first step would be to change answer to one of those. Second, what is raisingTo() returning. Unless your are doing something that's not evident, you don't need that, but it should still work. Also, both arguments should be doubles, according to this.
I am porting a legacy C program to C++. However, the compiler is not happy and requires additional typecastings for C++. For example, I have this function...
void foreach_element_in_patch(Patch *patch, void (*func)(),
long arg1, long process_id);
In the original C Code, it is used like this...
foreach_element_in_patch( patch, display_interactions_in_element,
mode, process_id );
However, for C++ I need to typecast the second argument to stop the compiler from gernerating an error.
foreach_element_in_patch( patch, (void (*)())display_interactions_in_element,
mode, process_id );
The error generated by the compiler is the following...
invalid conversion from ‘void (*)(Patch*, long int, long int)’ to ‘void (*)()’
Now is there a way to ask the compiler not to generate errors for such things. I have tried prefixing this function with extern "C" but still the C++ compiler is not happy. My applications is loaded with such code and I do not have the time to adjust so much code.
The error is quite clear, and your cast is invalid. You can't use a function that takes arguments as a function that doesn't take arguments.
For your code to work, you need to either:
Create a new function that calls display_interactions_in_element with sensible defaults.
Or use a capture-less and argument-less lambda that does the same (it might not be supported by your compiler, yet, though).
Note that if your code tries to call that function as if it took arguments later, it means the code is fundamentally broken.
Yes, there is a way. Compile your code as C.
C++ has stricter type safety rules, and requires you to explicitly cast types that could be implicitly converted in C.
So either compile the code as C, or make the modifications necessary for the code to be valid C++, and compile it as C++.
You should be able to compile your C files as C, your C++ files as C++, and then link them together without a problem.
But when you try to compile your C files as C++, the compiler is going to tell you if your code isn't valid C++.
I think your error comes from the fact that the function signature is has a different meaning in C and C++. The second parameter specification
void (*func)()
in C means "a function with an unknown number and type of parameters" and in C++ it means "a function without arguments". So these are quite different and it must crash.
The error is not in the lack of type safety of C, but in your code. Don't do that. Use strict prototypes, even in C. The correct parameter specification for both languages is just
void (*func)(Patch*, long int, long int)
that's it and everything is just blindly hacking around.
The easiest thing to do is to change the function prototypes and headers to declare the correct type of function pointer. So for example, for
void foreach_element_in_patch(Patch *patch, void (*func)(),
long arg1, long process_id);
I just need to change it to
void foreach_element_in_patch(Patch *patch, void (*)(Patch*, long int, long int),
long arg1, long process_id);
Instead of making changes at every function call.