Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I can pass arguments to a function in C in the following manner without any warnings or errors using gcc on ubuntu-64bit:
void func(char* test){
// do something here
}
void main() {
func((char*) "smaps");
}
I did not find a lot of examples about passing anonymous parameters to functions in C apart from one comment on a similar question about C++. I am thinking of using this technique (a lot) in my code which would be compiled on multiple AMD64/ARM devices as they become available (with mostly debian-based OSes). My question is, is this compiler-specific?
Output of gcc --version:
$ gcc --version
gcc (Ubuntu 6.3.0-12ubuntu2) 6.3.0 20170406
UPDATE: Even though I think 4386427's was good enough for me, I would explain a bit more about the question as it was put on hold. I have a script which makes several calls to a specific function which takes in a char** as argument. I was of the view that I would need to explicitly declare a char** separately and pass it to the function by name every time I made a call to the function. I thought it would be more convenient to declare a string and pass it to the function at the same time; something like:
func( (char**) {"first_string", "second_string"} ).
My initial concern was is this allowed in C generally or is this a compiler-specific feature? 4386427's answer suggests that it is not compiler-specific, however I should be careful that the char** passed to the function would be immutable.
All parameters in C are passed by value. No information about the original object from which the value came is passed to the called function. In this sense, all C arguments are anonymous; no information about the identifier used in the calling function is passed.
In func((char*) "smaps");, the string literal "smaps" is converted to a pointer to char. Only the value of the pointer is passed to func. This is standard C.
(If you do want to pass information about an object to a function, you must do that manually. For example, you can take the address of an object and pass the resulting pointer to the function. Or you can pass the number of elements in an array to a function, along with the address of the first element.)
(In C, string literals such as "smaps" are automatically converted to a pointer to their first character, so you do not need to manually convert them with a char * cast. [This automatic conversion does not occur when the string literal is the operand of sizeof, _Alignof, or & or when it is used to initialize an array.])
It depends on what you are doing in the function. As long as you don't try to modify what test is pointing to, there is no problem. To indicate that it can't be changed, it is good to add const.
Like this the code is fine:
#include <stdio.h>
void func(const char* test){
printf("%s\n", test);
}
int main(void) {
func("smaps1");
func("smaps2");
func("smaps3");
func("smaps4");
return 0;
}
But if you try to change the value like:
void func(char* test){
test[0] = 'A';
printf("%s\n", test);
}
you have undefined behavior because modifying a string literal is undefined behavior.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
#include<stdio.h>
void main() {
const int convalue=64;
int *point;
point = &convalue;
(*point)++;
printf("address of point is %p address of convalue is %p\n",point,&convalue);
printf("convalue is %d and point is %d\n",convalue,*point);
}
How can i modify the constant variable value
How can i modify the constant variable value
You cannot change the value of a constant1 after initialisation. That's what "constant" means.
You can change the program by removing the const qualifier. Then you can change the value. Or, you can conditionally choose another value during initialisation.
1 Except if the constant is of class type, then you can change mutable members of the object.
void main()
The pogram is ill-formed. main must return int in C++. It may not return void.
point = &convalue;
The pogram is ill-formed. A pointer to const doesn't implicitly convert to pointer to non-const. The type system of the language protects you from making mistakes such as this.
(*point)++;
The behaviour of the program is undefined. Const objects must not be modified. This is a bug. Don't write this in a program.
We can't and should never try to modify the value of a const variable. Also,
Any attempt to modify a const object results in undefined behavior.
Also,
note that undefined behavior means anything can happen including but not limited to program being successfully compiled and giving your expected output. But don't rely on the output of a program that has undefined behavior.
For more reading on undefined behavior you can refer to undefined behavior's documentation which mentions:
there are no restrictions on the behavior of the program.
Mistake 2
There is another mistake(in addition to undefined behavior) in your program(in C++). In particular, you should replace
int *point;//INCORRECT
with
const int *point;//CORRECT, note i have added const here
Mistake 3
You should replace void main() with
int main()
Because void main() is not standard C++ as Bjarne Stroustrup made this quite clear in this article
The definition void main() is not and never has been C++, nor has it even been C.
Simply – you can't. "Constant" is constant.
If you need to, you have to use variable instead.
Anyway, there is one possibility to get what you (maybe) want – preprocessor. Question is a bit strange, so I think you could be satisfied by that.
Using preprocessor you can determine what is the initial value of const. (And more, but that's not this case.) Still you can't modify it after it's initialized, but maybe it will be enough for you. For example:
#include<stdio.h>
void main() {
const int convalue=
#ifdef CLI_PROVIDED
CLI_PROVIDED;
#undef CLI_PROVIDED
#else
64;
#endif
int *point;
point = &convalue;
(*point)++;
printf("address of point is %p address of convalue is %p\n",point,&convalue);
printf("convalue is %d and point is %d\n",convalue,*point);
}
Normal compilation will initialize const with value 64. Compilation with option g++ -DCLI_PROVIDED=123 will modify initial value of const BEFORE compilation (this is just text operation) and then compile it with value 123.
Preprocessor is working with code before compilation.
If you want to (for example) create program for multiple operating systems, it will be useful.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
Let's say one wanted to create an array that could hold multiple function pointers & of different types.. how would he go about doing so ? Perhaps an array of void pointers could work ?... Well as it turns out, no since in order to use the functions stored in the void pointers you'd have to convert/cast them (the void pointers) back to function pointers and...
"A conversion between a function pointer and a void pointer is not possible. void* was never a generic pointer type for function pointers, only for object pointers. They are not compatible types.
[...] you can cast between void* and a function pointer, but what will happen is undefined behavior. You will be relying on system-specific non-standard extensions."
-#Lundin (here)
Instead...
Slightly better would be to use a function pointer type such as void (*)(void) as the generic pointer. You can convert to/from different function pointers, what will happen is compiler-specific (implementation-defined behavior). That is, the code will still be non-portable, but at least you don't risk a program crash from invoking undefined behavior.
-#Lundin (here)
That said, what does it even mean to convert from one function pointer to another ?
Could someone explain it. With an example perhaps.
It means that if you have two different function pointer types, such as for example:
int (*i)(int);
void (*v)(void);
Then you can make a conversion from one type to the other by using an explicit cast:
v = (void(*)(void))i;
This is allowed, but calling v() won't work. The standard says this, C17 6.3.2.3 §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 referenced type, the behavior is undefined.
So if you try to call the function by v(); then it is likely undefined behavior. You can however convert back to the original type int(*)(int) without losing information.
This allows you to use a specific function pointer type as a "generic type". Rather than using void*, which isn't ok, as discussed here.
Notably, all code with function pointers get much easier to read if you use typedefs:
typedef int int_func (int);
typedef void void_func (void);
int main()
{
int_func* i;
void_func* v;
v = (void_func*) i;
i = (int_func*) v;
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I need to write a lib wrapper. My wrapper function prototype looks like this
int my_wrapper(char * configstr);
The function to be wrapped looks like this.
void my_function(char config[CONFIGSTRSIZE]);
I tried to do the following:
int my_wrapper(char * configstr)
{
my_function(configstr);
return 0;
}
This compiles and works but I receive an error. Telling my that the argument is a invalid type.
discards qualifiers from pointer target type
Is there a way to perform a cast to telling the compiler that the pointer of the calling function always is a pointer of the proper size?
It's more or less impossible to change the interfaces. I thank you for your feedback.
Is there a way to perform a cast to telling the compiler that the
pointer of the calling function always is a pointer of the proper
size?
It is not possible in C. Pointers do not have information about the size. You need to pass it as the additional parameter or have this information in the dereferenced object (for example first is the size, or termination value like C strings)
First of all, the following function declaration doesn't make much sense, although legal:
void my_function(char config[CONFIGSTRSIZE]);
It creates the wrong impression that you can somehow pass an array (with a fixed size). You can't in C. What actually happens is that C adjusts any array type in a function declaration to a corresponding pointer type, so this declaration ends up to be just
void my_function(char *config);
You could write it like this to emphasize that the pointer passed should point to an array (I prefer not to, but that's a matter of style):
void my_function(char config[]);
Now for your problem, according to the error message you get, you're probably trying to pass a const-qualified pointer here. Depending on what my_function() is doing, there are two solutions:
my_function() only reads the array. Then you should change the function prototype like this:
void my_function(const char *config);
my_function() also modifies the array. Then you can't pass some const data there, but you might take a copy of your data. Assuming the data is a string, one way to do it would be the following:
// having some const char *config
char *cfgcopy = malloc(strlen(config)+1);
if (cfgcopy) { // allocation succeeded
strcpy(cfgcopy, config);
my_function(cfgcopy);
// do something with the modified cfgcopy
free(cfgcopy);
}
Instead of malloc()/strcpy(), many implementations provide a "shorthand" strdup() function you could use. But be aware strdup() isn't part of standard C.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
Is the following code in C correct? I am not 100% sure about the scope of function parameter "a":
void method(int a)
{
MyStruct mystruct;
mystruct.value = (void*) (&a);
nested_method_call(mystruct);
}
Let's assume it's:
void method(int a)
{
MyStruct x;
struct.value = (void*) a;
nested_method_call(x);
}
since struct cannot be used as a variable name.
a's scope is the function, so it is alive during nested_method_call, however, that is absolutely irrelevant because your nested_method_call isn't referring to it -- it's using a copy of a reinterpreted as void*. (Such reintepretation makes the code quite unportable and unusual, by the way. It might be a mistake.)
Edit:
void method(int a)
{
MyStruct mystruct;
struct.value = (void*) &a;
nested_method_call(mystruct);
}
is valid (though it's usually a good idea to pass structs by pointer because it's faster for any but very small structs). &a is a valid reference until the } of method.
You also shouldn't need that cast. If .value is void*, you don't need it. If it isn't, the cast makes &a convertible to any other data pointer, which is potentially a dangerous hole in the type system.
First of all, struct is a keyword in C and cannot be used as a variable name, so this is wrong code.
After that, casting an integer to pointer (and vice-versa) is implementation defined behaviour. You should better use uintptr_t for better, if you have to get that conversion done.
That said, from the basic premises of your question, the logic behind the code seems legit, there's no problem with the scope. In case you meant to ask about the lifetime ["The lifetime of an object is the portion of program execution during which storage is
guaranteed to be reserved for it"], then, it is until the end of the method() function and you're using it inside that limit, so you're good to go.
Corrected code: struct.value = (void*)&a;. Also some other validation needs to be done.
So, if you fully correct your code so that it complies properly then Correct word would be Lifetime instead of Scope. Lifetime of a will be till the end of function method. Therefore, a can still be accessed inside nested_method_call via pointer struct.value assuming type of struct.value is int*.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I define a function, let's say myfun in file2.c. myfun returns a float value. In file1.c I don't have any declaration for this function. I directly call myfun without any prior declaration and assign it's return type to an integer variable, let's call it retValInt. I compile them together. When I print retValInt, it gives me garbage. Why doesn't it cast the returned value and give the appropriate integer?
The following is the exact code:
//file1.c
#include<stdio.h>
int main()
{
int retValInt = myfun(123.456);
printf("The value returned is %d\n",retValInt);
return 0;
}
//------------------------
//file2.c
float myfun(float a)
{
return a;
}
I expected the output to be 123, but it is 446676599.
How could the compiler possibly know, when compiling main, that myfun returns a float that needs to be cast to an int?
You're asking why the compiler didn't make the code do something it could not possibly have known it needed to make the code do. So the answer is obvious -- the compiler had no way to know that's what you wanted. In fact, it is reasonable for the compiler to assume that if you wanted it to do that, you would have told it to. So one can argue that the behavior you seem to expect would actually be incorrect and quite baffling. (You never told the compiler to do that, so doing it would be bad.)
In C, specifically in C89 (but not in C99 or C11!), functions that have not been declared are implicitly assumed to have return type int. If your actual function does not have that return type, your program is ill-formed (it has undefined behaviour), and no diagnostic is required.
Your code is not valid C99, but compiler support for C99 is half-hearted at best.
To write a prototype before using the function.
float myfun(float);
int main()