c - How to avoid getting warning assignment of different pointer when passing function with specific type parameters? - Stack Ov

I have written this example to try and explain the problem.I have defined a function as follows: Re

I have written this example to try and explain the problem.

I have defined a function as follows:

// Return name from given user.
typedef char *(name)(void *user);

And then implemented this function as follows:

// Return name for a System 1 User.
char * system1_user_name(System1User *user)
{
    return user->name;
}

And then I have a function which takes an argument of type void which it then passes to the second argument of type name (the function).

void say_hello(void *user, name *name)
{
    printf("Hello %s\n", (name)(user));
}

I then call the say_hello function as follows:

say_hello(&system1user, system1_user_name);

The solution compiles and run as expected, however during compilation it gives the warning "assignment of different pointers" specifically because the name function expects a void argument but the argument of the implemented function system1_user_name takes an argument of type System1User.

Now I know I can resolve the warning by doing this:

char * system1_user_name(void *user)
{
    System1User *u = (System1User)user;
    return u->name;
}

However I was wondering if there is any way how I could keep the function signature as is because system1_user_name expects an argument of type System1User and assuming this function is used for example in other areas of the solution (not just as a callback for the say_hello function) it would either potentially be misleading (as it expects an argument of type void *) or else require to stay writing a second function just to be used as an argument to the say_hello function.

Given that passing anything to a void * argument works I was expecting that having a callback function with arguments set to void * would also work. However, while the compiled solution does work as expected, the compiler still gives warnings. For me the function definition saying it accepts anything (therefore void *) makes sense, but implementing that function using void * feels wrong and misleading as the implementation is working on an actual type. I wonder if there is a clean solution to the problem.

I have written this example to try and explain the problem.

I have defined a function as follows:

// Return name from given user.
typedef char *(name)(void *user);

And then implemented this function as follows:

// Return name for a System 1 User.
char * system1_user_name(System1User *user)
{
    return user->name;
}

And then I have a function which takes an argument of type void which it then passes to the second argument of type name (the function).

void say_hello(void *user, name *name)
{
    printf("Hello %s\n", (name)(user));
}

I then call the say_hello function as follows:

say_hello(&system1user, system1_user_name);

The solution compiles and run as expected, however during compilation it gives the warning "assignment of different pointers" specifically because the name function expects a void argument but the argument of the implemented function system1_user_name takes an argument of type System1User.

Now I know I can resolve the warning by doing this:

char * system1_user_name(void *user)
{
    System1User *u = (System1User)user;
    return u->name;
}

However I was wondering if there is any way how I could keep the function signature as is because system1_user_name expects an argument of type System1User and assuming this function is used for example in other areas of the solution (not just as a callback for the say_hello function) it would either potentially be misleading (as it expects an argument of type void *) or else require to stay writing a second function just to be used as an argument to the say_hello function.

Given that passing anything to a void * argument works I was expecting that having a callback function with arguments set to void * would also work. However, while the compiled solution does work as expected, the compiler still gives warnings. For me the function definition saying it accepts anything (therefore void *) makes sense, but implementing that function using void * feels wrong and misleading as the implementation is working on an actual type. I wonder if there is a clean solution to the problem.

Share Improve this question asked Jan 29 at 18:17 sja785sja785 311 silver badge3 bronze badges 1
  • 1 No, I don't think you can do what you want. This is similar to the qsort() comparison function declaration, and these always have to be written with the cast. – Barmar Commented Jan 29 at 18:23
Add a comment  | 

2 Answers 2

Reset to default 0

Your code invokes Undefined Behaviour and silencing the warnings will not make the program compliant. You need to change the signatures of the function.

The solution compiles and run as expected

That is the beauty of the UB. It can run OK on one platform, but not another or if compiled using a different compiler. Your claim is false. You have to remove the UB.

I have defined a function as follows:

// Return name from given user.
typedef char *(name)(void *user);

No, you did not. You defined an alias for a function type. There's no actual function there.

And then implemented this function as follows:

// Return name for a System 1 User.
char * system1_user_name(System1User *user)
{
    return user->name;
}

In the terminology of the language spec, you appear to mean that you implemented a function whose type is compatible with name. But no, you (probably) did not do so. Among the requirements for two function types that include prototypes to be compatible is that they must have the same number of parameters, and corresponding parameters must have compatible type. Although there are automatic conversions back and forth between pointers to void and pointers to other object types, pointers to void are not compatible with pointers to any other type, in the relevant sense of "compatible". Therefore, unless your System1User is an alias for void, no, the type of system1_user_name is not compatible with name.

The solution compiles and run as expected,

Yes, that can happen with programs whose behavior is not defined by the language spec. Under some circumstances, that can even be reliable.

however during compilation it gives [a warning about incompatible pointer types]

That's not surprising, because such a warning is warranted.

Now I know I can resolve the warning by [modifying system1_user_name to be compatible with type name, but] I was wondering if there is any way how I could keep the function signature as is.

Your function's type is not compatible with type name. You cannot make them compatible without changing one or the other. However, you could provide a shim in the form of a wrapper function that you interpose between say_hello() and system1_user_name(), as presented in @Darth-Codex's answer. That will resolve the issue your compiler warns about (not only resolve the warning), at the cost of introducing another potential issue that the compiler probably will not diagnose: if you ...

say_hello(&some_object, system1_user_name_wrapper)

... for a some_object whose type is not System1User (primarily; or one of a narrow family of others) then the behavior is still undefined.

Shimming system1_user_name like that is better than what you're doing now, because the resulting behavior is well defined as long as you pass in only pointers of suitable type. That will help protect you against your compiler deciding to do something wacky when it optimizes your program, but you should not take the resulting lack of diagnostic messages as a sign that you've resolved all issues.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745285118a4620513.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信