Scope for function parameter in C [closed] - 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*.

Related

How to change or modify value of const variable? [closed]

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.

C: What even is function pointer conversion? [closed]

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;
}

Passing anonymous parameters to functions in C [closed]

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.

How to pass a pointer to a function argument of type fixed size array? [closed]

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.

function pointer and void pointer [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I'm writing code for an embedded system. The compiler is a GCC derivative.
Is the following code correct?
void *voidPointer = 0;
int (*functionPointer)(int a);
int testFunction(int a)
{
return(a+1);
}
void registerFunction(void *pvFunctionAddress)
{
voidPointer = pvFunctionAddress;
}
main()
{
...
registerFunction(testFunction);
functionPointer = voidPointer;
x = functionPointer(17);
...
}
Now x should have the value 18.
The compiler does not show an error - but is this correct?
Or do we overwrite some memory on the stack.
Thanks.
No, it can never be "correct" since strictly speaking C forbids conversions between void * and function pointers.
If it works, it's because a particular compiler allows it for that particular target (operating system + hardware combination).
Strictly speaking, according to the C standard, a void* is not guaranteed to be able to hold a function pointer. I believe that POSIX does require that a function pointer be able to be stored in a void* (in order to support the dlsym() function). See https://stackoverflow.com/a/12359083/12711
Let's say it like this:
In C a function is identified by the address of the first instruction in the appropriate assembly that begins it's execution and it's calling convention, thus a void* is a valid storage class to store it if the calling convention is a compile-time constant. For most commonly used CPU architectures it is.
If your code works with your compiler for your target hardware then it it correct in that sense.
Here is a simple comparison:
uintptr_t i = NULL;
is valid C because uintptr_t (normally unsigned long int) is the same storage class as void * (type of NULL).

Resources