I'm trying to call a function (on line 15) just via a cast but only the first argument is getting passed, how could I fix it?
I tried to change the float value "2" to 2.0f to declare it's a float and not an int but it's still not working.
!Note that the code is horrible because it's a code golf, the line 15 has to be in a dll form later, this code here is just a test program to avoid launching the target process multiples times. Here's my actual code with a score of 58 chars
DllMain(a,b,c){((int(*)(int,float))927309216)(7903472,2);}
#include <Windows.h>
#include <stdio.h>
char * sSkelModelStencil = "SkelModelStencil"; //here I reproduce the char like it is in the memory
void SetConsoleFloat(const char *sKey, float fVal) //this is the reproduction of SetConsoleFloat in CShell.dll
{
printf("arg1: %s arg2: %f\n", sKey, fVal); //printing the arguments getting passed into the function
return;
}
int main()
{
while (1) {
SetConsoleFloat("SkelModelStencil", 2); //calling the reproduction function
((int(*)())SetConsoleFloat)(sSkelModelStencil,2); //calling the reproduction function via a cast & using SetConsoleFloat addr
system("PAUSE");
}
}
In some architectures, the way arguments are passed depends on the way they're declared. For instance, special registers may be used for float parameters. It's the declaration of the function type that matters, not the declaration of the argument expression.
The parameter signature () is different from (const char *sKey, float fVal), and as a result the fVal argument is being passed differently from the way the function expects to receive it.
First of all - this is atrocious code, don't do that.
Secondly - compile your code with compiler warnings on, so the compiler can tell you where you might be going wrong. Of course, you need a proper C compiler (which MSVC is not, in case you were using that). gcc will tell you:
a.c:15:10: warning: function called through a non-compatible type
But, to answer your question: You're casting into the wrong type of function: You're using the function type void (); but you need void (const char*, float). So, try:
((void(*)(const char*, float))SetConsoleFloat)(sSkelModelStencil,2);
instead of your existing line 15. It's also a good idea to separate casts from type definitions of functions - for clarity - so you would have:
typedef void (*scf_function_t)(const char*, float);
earlier, and then:
((scf_function_t) SetConsoleFloat)(sSkelModelStencil,2);
but again - there's really no good reason to do any of this in the first place.
Related
I am trying to print the value of a local variable inside of main, from another function without using global variables. What would be the best way to do so?
#include <stdio.h>
int function1();
int main(void) {
int hello=10;
printf(function1());
}
int function1(int ip){
printf("hello%d",ip);
}
I am expecting the 10 to be printed next to the "hello" but instead get a 0.
You need to call the function passing the value (or variable) required.
int function1(int);
int main(void)
{
int hello=10;
function1(hello);
function1(130);
}
int function1(int ip)
{
return printf("hello - %d\n",ip);
}
https://godbolt.org/z/97o3dPWzj
change
int function1();
to
int function1(int);
and
printf(function1());
to
function1(hello);
"I am expecting the 10 to be printed next to the "hello" but instead get a 0."
There are already examples of working versions of your code in the other answers, but little is said in the way of explanation. I will try to do that here, and offer some general suggestions.
Although your code compiles, it does so with warnings and when run, produces run-time errors. The information resulting from both of these, if heeded would likely provide a guide to addressing most of your issues. (If using GCC for example, you can set warnings to -Wall). To illustrate, here is an image showing line numbers and the warning that correspond with them on my system (not GCC, but warning are turned on)
Build warnings:
And finally, run-time error:
From these you can begin to derive some of the following observations (others listed are my own.)
The signature of a function prototype must match its implementation. (for function1, they do not)
If the prototype of a function is non-void, then it should return a value.
If a function returns a value, its return value should not be ignored.
The warning of an unused variable pointed out that you probably intended to use it as an argument here: function1()
See comments below for other clarifications:
int function1();//this prototype is incomplete, and is inconsistent
//with the signature of its implementation
int main(void) {
int hello=10;
printf(function1());//because function1 is not returning a value, your code outputs a 0
//Function1 prototype requires it to pass an argument
// non-void function should return a value here
}
int function1(int ip){//signature of this implementation disagrees with its prototype
//because there is no value passed, ip can be any value
printf("hello%d",ip);
// non-void function should return a value here
}
I'm studying C and my book is explaining how to "prototype a function" so we can use it before we define it.
The point is that I can't imagine a situation in which is needed to use a function before have defined it, why can't we just define it at the beginning?
Can you please provide an example in which is strictly necessary to prototype a function (if it exists)?
Consider the program below:
#include <stdio.h>
void add(int, int);
int main() {
add(5, 3);
return 0;
}
void add(int a, int b) {
printf("%d", a+b);
}
Here, when you call add(5, 3) from main(), the compiler knows what add() is - the parameters it takes and the return type, thanks to the statement void add(int, int) in line 3. If this statement is commented out, then the compiler won't know what add() is and would give you an error. Thus, line 3 tells the compiler that you have defined the function add() later, which makes it perfectly eligible to be used in main(). Alternately, if you write the add() function before main(), then the compiler knows what add() is when you call it; so a function prototype is not required in this case.
Hope this is useful.
One use-case is when you want to take a function pointer to a function defined in another source file. (Or hand-written in asm). Taking a function-pointer always requires the function to be declared ahead of time, either by a definition or a prototype.
C89 (and earlier) allows implicit declaration of functions (use them even if there's no definition or prototype earlier in the compilation unit (this .c + anything you #include).
So you can compile this in a file by itself, in C89 (or with a warning from most compilers in C99 / C11 mode)
int foo() {
return bar( 123 ); /* implicit declaration of int bar() */
}
But you can't use &bar as a function pointer
/* int bar(int); necessary if you haven't defined int bar(int x) { ... } */
void *take_fptr() {
return &bar; // error: 'bar' undeclared from GCC
}
You can also construct cases where a declaration is needed to get args passed correctly, e.g. if you want your function to take a float arg, you need it to be declared, either by a definition or prototype. The "Default Argument Promotions" in the ISO C standard will promote float to double when passing an arg to an unprototyped function, or to the ... part of a variadic function like printf.
(That's why %f prints a double, not a float, and why %lf is also a double if it's supported at all. Also why functions like putchar(int) take their char arg as an int: default promotions of narrow integer types up to int. Some parts of the C standard library date back to very early C, before the language supported prototypes!)
Or for example, if your function is expecting a long long, but the caller writes bar( 123 ), the caller will only infer int, which may be passed differently from a long long. But you can fix that by writing bar( 123LL ), or bar( (long long)123 )
Or if the return type isn't int (or void), then you also need the compiler to know about the function via a declaration. Implicitly-declared functions are assumed to return int. Depending on the calling convention and architecture, you might get away with that for a short return type, or on some machines even for a char*, e.g. on 32-bit machines where intptr_t is int. (Early C relied on that.)
But in general, e.g. on machines with 64-bit pointers, implicit-int return isn't going to work. Nor will it work for a double return value, or a struct.
The definition of the function may not be known at that time. Imagine a program that calls malloc to allocate memory. At compile time, nobody has any idea what allocator the program will be using at run time. So how can you define the function then?
Background
I'm using the C interface to the GMP library and I have a need to manipulate arrays of integers. Main type for integers in the GMP library is mpz_t, and GMP is using a trick to allow the users to use gmp_z without explicit allocation, while being able to pass them around as pointers. Namely the gmp_z type is defined as follows.
typedef struct
{
int _mp_alloc;
int _mp_size;
mp_limb_t *_mp_d;
} __mpz_struct;
typedef __mpz_struct mpz_t[1];
This is neat, but I am having trouble passing arrays of mpz_t to functions that operate on const arrays.
Example
To exemplify consider this simple non-GMP program.
#include <stdio.h>
typedef struct {
int x;
} x_struct;
typedef x_struct x_t[1];
void init_x(x_t x) {
x->x = 23;
}
void print_x(const x_t x) {
printf("x = %d\n", x->x);
}
// I'm just printing so taking a const array
void print_x_array(const x_t* x_array, size_t n) {
size_t i;
for (i = 0; i < n; ++ i) {
printf("x[%zu] = %d\n", i, x_array[i]->x);
}
}
int main() {
x_t x; // I can declare x and it's allocated on the stack
init_x(x);
print_x(x); // Since x is an array, pointer is passed
x_t x_array[3];
init_x(x_array[0]);
init_x(x_array[1]);
init_x(x_array[2]);
print_x_array(x_array, 3); // Compile warning
}
The program uses the GMP trick, just showing off the usage. Compiling this program gives an annoying warning
gcc test.c -o test
test.c: In function ‘main’:
test.c:33:3: warning: passing argument 1 of ‘print_x_array’ from incompatible pointer type [enabled by default]
test.c:17:6: note: expected ‘const struct x_struct (*)[1]’ but argument is of type ‘struct x_struct (*)[1]’
Question
Since I'm not a C expert, can someone please shed more light on why this warning is happening at all. More importantly, is there a way to get around this warning while still using mpz_t (or x_t in the example)?
Just cast it to const:
print_x_array((const x_t *)x_array, 3); // Should be ok
First, let's note that the compiler warning you are getting has absolutely nothing to do with GMP, their strategy of typedefing a mpz_t type as an array of size one so that it facilitates some function calls within the library (but only facilitates scalar argument passing), nor to the passing of arrays to functions, and nor its a real problem in itself actually.
The problem all relies on the const declaration of function parameter input, and that is not a true issue. Its good to have that definition, so compiler will balk if function writer attempts to modify the object being passed to the function. But burden cannot be put on function callers!
In my setting (OpenSUSE, x86_64, gcc version 9.2.1) your code does not gives a warning and works perfectly fine if I don't use the -pedantic compiler option. This is because, as Michael Pankov stated, the (old) C standard is pretty tight and sometimes cumbersome, while compilers today are very smart. The compiler does now what you want, and will provide you correct code, be assured of that. Also, in your environment it seems there will be many more people calling the function than changing it, so it can be quite assured the input will not be unduely modified, and you can ignore the warning altogether.
For ignoring this specific warning check here for GCC, other compilers also provide this options.
About the const on function parameter input check here, I particularly like this answer: "If your code has many people working on it and your functions are non-trivial then you should mark const any and everything that you can. When writing industrial-strength code, you should always assume that your coworkers are psychopaths trying to get you any way they can (especially since it's often yourself in the future).".
I don't understand why the following code generates a warning:
int func(double a, int b, char c)
{
return 0;
}
int main()
{
int(*myPointer)() = func;
return 0;
}
I thought that in C, a function with an empty parameters list mean a function that can receive an unknown number of parameters. func4 happens to receive 3 parameters. So why is it incompatible with myPointer?
Its especially confusing because the following does compile without warning:
void boo()
{
return;
}
int main()
{
int(*pointerDude)(double) = boo;
return 0;
}
What's going on?
The difference between the two cases is explained like this: if you pass a parameter to a function that accepts none, you are just consuming some memory on the stack. If you don't pass any parameter to a function that accepts a few, the latter is going to read random data from the stack.
Update: changed to community wiki to add these corrections from Pascal Cuoq:
Casts of function pointer in both directions are legal, informative warnings from the compiler notwithstanding. Calling a function with the wrong prototype is illegal in both cases. Some ABIs mandate that the function clean up the stack, in which case passing parameters to functions that accept none corrupt the stack as surely as not passing parameters to functions that expect them.
C99 6.3.2.3 par. 8:
A pointer to a function of one type may be converted to a pointer to a
function of another type and back again; the result shall compare
equal to the original pointer. If a converted pointer is used to call
a function whose type is not compatible with the pointed-to type, the
behavior is undefined
This is the warning you get:
warning: initialization from incompatible pointer type
You are passing void which means that will require a cast. You should use the right types.
IIRC C compiler has certain assumptions which can cause very odd bugs because you're not telling it how much stack space it needs whenever that function is called. Especially since the definitions don't match this might allow someone to inadvertently read your function pointer declaration and assume no parameters and have the function return garbage. If you really want to take variable numbers of parameters use my_func(...) and varargs.
A warning is just that, a warning. Honest.
In that case, the compiler knows you have an incorrect function pointer type and it blatantly tells you that. If you try to pass a number of parameters different then 3, then it will be issued an error.
I think that the problem is related to the casting of the parameters, because char is not 32 bits. Note that if you change the char to int this works fine. It is related to automatic promotion of variables.
Compare the two:
int func();
int func(double a, int b, int c)
{
return 0;
}
and
int func();
int func(double a, int b, char c)
{
return 0;
}
gcc gives you warning for the second, but not for the first
In C an empty parameter list means that the function does not take any parameters. I believe you are confusing an empty parameter list with varargs.
Changing your first example to include the parameters will remove the warning.
int func(double a, int b, char c)
{
return 0;
}
int main()
{
int(*myPointer)(double, int, char) = func;
return 0;
}
I have a function pointer inside a struct that gets dynamically set at runtime to the address of another function in various places in my code. It is defined in my header file like this:
void *(*run)();
During compile time, I get the following warning about this:
warning: function declaration isn't a prototype
This warning is benign, because the pointer is used in many places in my code to call the function it points to, and everything works just fine. However, I would really like to silence the warning.
If I change it to this:
void *(*run)(void);
I get compile errors whever I use it, because the various functions that make use of the pointer have different numbers of arguments, and saying void inside the parenthesies tells the compiler it accepts no arguments.
I can't use a va_list or anything fancy like that, as this is simply a pointer to another function, and I use a single pointer for them all because it keeps the code clean and simple.
I can silence the warning with adding this to my compiler flags:
-Wno-strict-prototypes
But I'd rather not have to disable compiler warnings with flags if I can avoid it.
So my question is: How do I notate this function pointer in the code in such a way that the compiler is satisfied with the fact that it accepts any number of any kind of arguments?
The code works perfectly. I just want the warning to go away.
Store the pointer as a void * and cast to the appropriate function pointer type when necessary? Keep in mind that it isn't necessarily safe to call one type of function pointer as if it were another type, so the warning you're starting out with isn't entirely invalid.
You can cast a function pointer like so:
void *genericPointer = ...;
void (*fp)(int, int) = genericPointer;
fp(123, 456);
Note that:
There's no explicit casting necessary here, as void * can always be cast to any pointer type.
The initial "void" before (*fp) is the return type of the function pointer.
You are trying to do things clean - i.e. involve the compiler in checks, but the design you invented simply cannot be clean by its principle. You cannot involve compiler in prototype checks this way, because you always must know, which parameters to pass at this particular case in runtime. Compiler cannot check this and if you make a mistake, segmentation fault is on the way.
But if I remember well, something like this was maybe used also in linux kernel (?). The solution is to have a general pointer (like the one you have) and each time you call a particular function you just typecast it to the pointer to function with the particular arguments. You may need to typecast it to void * first to silence the compiler again :-)
In C, when you call a function without a prototype visible, default argument promotions are applied to all of the arguments that you pass to the function. This means that the types that you actually pass do not necessarily match the types received by the function.
E.g.
void (*g)();
void f()
{
float x = 0.5;
g(x); // double passed
}
This means that you need to know that the function that you are actually calling has a compatible signature to that implied by the arguments that you are passing after promotion.
Given that you need to know this in any case you must know the function signature of the actual function being called at the call site which is using the function pointer. With this knowledge it is usually simpler and cleaner to use a function pointer with the correct prototype and you can avoid default argument promotion entirely.
Note that as you are defining your functions with prototypes, when you assigned a pointer to your function to a function pointer without a prototype you effective converted, say, a void(*)(int, int) to a void(*)() so it is completely correct and desirable to perform the reverse conversion before calling the function. gcc allows both these conversions without emitting any warnings.
E.g.
void PerformCall( void(*p)() )
{
if (some_condition)
{
// due to extra knowledge I now know p takes two int arguments
// so use a function pointer with the correct prototype.
void(*prototyped_p)(int, int) = p;
prototyped_p( 3, 4 );
}
}
Try typedefing the function pointer declaration and then have the caller explicityly cast it:
typedef void *(*run)();
//when calling...
void my_foo() {}
run r = (run)my_foo;
If the different function signatures are known, use a union. Otherwise, use a pointer of type void (*)(void) (actually, any function pointer type would do) to hold the generic pointer and convert to the proper type when setting the value and calling the code.
Example using a union:
union run_fn
{
void *(*as_unary)(int);
void *(*as_binary)(int, int);
};
struct foo
{
union run_fn run;
};
void *bar(int, int);
struct foo foo;
foo.run.as_binary = bar;
void *baz = foo.run.as_binary(42, -1);
Example using explicit casts:
struct foo
{
void (*run)(void);
};
void *bar(int, int);
struct foo foo;
foo.run = (void *(*)(int, int))bar;
void *baz = ((void *(*)(int, int))foo.run)(42, -1);
Don't use a void * to hold function pointers - such a conversion is unspecified by the ISO C standard and may be unavailable on certain architectures.
Ignoring the warning and using your code as-is is actually also a possibility, but keep in mind that any function argument will be subject to the default argument promotions and it's your responsibility that the promoted arguments properly match the declared parameters.