I have an assignment that requires the use of a function
void stats(FILE *in, int *count, double *sum); , which is supposed to compute the sum, average, and integer count of each file. We are supposed to call the function by using stats(in, &count, &sum) . I'm confused as to how exactly I'm supposed to send the results back to main if the stats function has a void return type. Any help or explanation would be greatly appreciated! Thanks
Your function signature indicates that each parameter is a pointer argument (they begin with a *). Declare (and possibly initialize) those variables in your main function, then pass the addresses of those variables as indicated in the way you're told to call the function: stats(in, &count, &sum). The function will modify those variables in main scope using the pointers you passed to it, without returning any value. This is an example of pass (or call) by reference.
So overall, your main function will have something like:
int main(void)
{
/* some FILE opening here */
int count = 0;
double sum = 0;
stats(in, &count, &sum);
/* rest of your main function */
return 0;
}
If you want to understand more about what the * and & mean, you should go through how pointers work in C – here is a very basic resource to get you started.
Related
H.ello just a hobbyist here. I started again C after a little JS detour that taught me closures, oop and other stuff. I usually make small code snippets that I can reference or reuse later. So in the code below is there a reason why the compiler says counter is undeclared, as it is referenced as an argument of the callback function argument?
To make this work,
1. I could make counter a global variable, this works but it is not best practice.
2. I could move caller function inside main, but I'd like to avoid this.
3. pass counter as a 4th seperate pointer argument, however in that case, I don't really know with what voodoo should I invoke the caller function popArr within main.
Generally I'm interested in the technique how to use callbacks with arguments without using global variables or putting everything inside main.
So here is the code:
#include <stdio.h>
// CALLBACKS
/* Caller */
void popArr(int *arr, size_t length, int (*callback)(int *counter)) {
for (size_t i=0; i<length; i++) {
arr[i] = callback(&counter);
printf("arr[%zu] is: %d\n", i, arr[i]);
}
}
/* A simple generator callback saving counter. */
int generator(int *counter) {
*counter = *counter+1;
return *counter*5;
}
/* Main function. */
int main(void) {
int counter = 1;
int arr[10];
popArr(arr, 10, &generator);
return 0;
}
So in the code below is there a reason why the compiler says counter
is undeclared, as it is referenced as an argument of the callback
function argument?
I presume you mean in function popArr(). Yes, of course there's a reason. In popArr(), the symbol counter appears only in the prototype for the callback function, and the scope of that appearance is limited to the prototype in which it appears. There is no symbol with that name in scope in the body of popArr().
The different appearances of the symbol counter in that prototype, in function generator(), and in main() all have different, non-overlapping scope. They are not related to each other, notwithstanding the reuse of the same name.
Generally I'm interested in the technique how to use callbacks with arguments without using global variables or putting everything inside main.
There are two main scenarios:
Callbacks with parameters that the caller (popArr() in your example) is expected to choose itself, and
Callbacks with parameters that the callback provider (main() in your example) is expected to specify.
Those are not mutually exclusive. Case (1) has no special requirements -- the caller just passes whatever argument is appropriate, at its own discretion. Case (2) isn't much harder, in principle: the code that provides the callback simply needs to provide the appropriate argument with it. For your very simple case, where the argument and callback do not need to be stored, that would look something like this:
void popArr(int *arr, size_t length, int (*callback)(int *), int *counter) {
// The name of the parameter to (*callback)() is omitted for clarity. It is
// optional in this context.
for (size_t i = 0; i < length; i++) {
arr[i] = callback(counter); // Note: passing counter, not *counter
printf("arr[%zu] is: %d\n", i, arr[i]);
}
}
/* A simple generator callback saving counter. */
int generator(int *counter) {
*counter += 1;
return *counter * 5;
}
/* Main function. */
int main(void) {
int counter = 1;
int arr[10];
// It is unnecessary, but not harmful, to use the & operator on the function
// name. I think it's better style to omit it.
// It is necessary to use the & operator on 'counter', but mainly because
// you want to pass a pointer to counter, as opposed to its value
popArr(arr, 10, generator, &counter);
return 0;
}
I would like to pass a parameter from my main() into my function. Please let me know how should I do that. I saw some methods in Internet but they didn't work.
Here is the code:
void *deliver(int *i)
{
int *ThreadID=(int *)tid;
//Here I would like to do some comparing on arrays using i parameter
//a[i]>b[i] As an example
}
void main ()
{
pthread_t t2_deliver[100];
//input var
printf("By using this code you can apply T threads on ordering list ;) \n");
printf("->*******************************************************************************<-\n");
printf("Please enter the number of threads(T):\n");
scanf("%d",&threadnum);
for (i=0; i<threadnum; i++)
{
pthread_create(&t2_deliver[i],NULL,deliver,&i);
}
You have a logical error in your code. All threads you create will have a pointer to the same i, meaning it will have the same value in all threads, and will most likely be out of bounds as the threads will run after the loop creating the threads.
One possible solution is to use casting and the standard intptr_t to pass the value to the thread functions:
pthread_create(..., (void*) (intptr_t) i);
And in the thread:
void *deliver(int *p)
{
int i = (int) (intptr_t) p;
...
}
First error that I see is you try to cast not what is in i (argument of function) but in some variable tid.
In principle thread function (in your case deliver) accepts as an argument void pointer, which later can be casted to what you sent, so just to play by the rules I would recommend you that you change function definition so it accepts void pointer as argument, not int pointer. It should not make any difference but is more correct. Why is this better: void pointer is a pointer to some data we don't know yet what it is so we need to cast it in function, this gives us the freedom that we could pass to function whatever we want from simple integers to complex structures. If you then want to get the value that is stored on location passed as function argument you dereference it with * operator. So I'm suggesting you make this modifications, thread function should look something like this:
void *deliver(void *i){
// in p there is integer pointer to argument i
int *p = (int *)i;
// now in ThreadID we have value of argument we passed to function in main (value at address i)
int ThreadID = *p;
//Here I would like to do some comparing on arrays using i parameter
//a[i]>b[i] As an example
}
and when creating threads just to do it right I would do this:
pthread_create(&t2_deliver[i],NULL,deliver,(void *)&i);
Maybe some of the things like type of pointer are not necessary but I think it is more correct and by my experience this works fine and you get the freedom to pass to function everything you want if you then cast it and dereference it correctly. Hope this helps.
Update and fix:
As mentioned in a comment below by Jonathan Leffler passing address of i in for loop (main function) is wrong, because then all threads point with their arguments to the same integer i in memory and effectively to the same value. There are plenty of workarounds, two are mentioned below by Jonathan Leffler, my favourite is constructing array of ids and then assagning and sending each id in array to each of threads:
ind tid[100];
for (int i = 0; i < 100; i++){
tid[i] = i;
pthread_create(&t2_deliver[i],NULL,deliver,(void *)&tid[i]);
}
Sorry for my mistake.
What are Function Pointers in plain English?
In simple english,
A FUNCTION_POINTER is a pointer which points towards the address of
fuction's first instruction, like a POINTER which points towards the
address of a variable.
Take a example of a program to understand the concept
Sum of all integers upto the user i/p
-
#include <stdio.h>
int IsAny(long n)
{
return 1;
}
long AddIf(long limit, int (*funPointer)(long))
{
long sum = 0;
register int i;
for(i = 1; i <= limit; ++i)
{
if(funPointer(i))
sum += i;
}
return sum;
}
int main(void)
{
long l, total;
printf("Enter a positive integer: ");
scanf("%ld", &l);
total = AddIf(l, IsAny);
printf("Sum of all integers upto %ld is %ld\n", l, total);
}
Here FUNCTION_POINTER is called to call IsAny function in AddIf with a declaration
as int (*funPointer)(long)) in AddIf function
As you asked in plain english, let's give it a try.
A pointer is an address in memory. A pointer has a type so the program can "find" the object you are refering to when using your pointer.
A function pointer uses the same logic. It declares a function that will be used has a method parameter for exemple. So you know that you will use a function that will have an input and an ouput in that method but the logic in that function don't need to be known.
From there you can send any function pointer to be used as the program only concern is that you will send and receive predefined types.
According wiki
A function pointer (or subroutine pointer or procedure pointer) is a type of pointer supported by third-generation programming languages (such as PL/I, COBOL, Fortran,1 dBASE dBL, and C) and object-oriented programming languages (such as C++ and D).2 Instead of referring to data values, a function pointer points to executable code within memory. When dereferenced, a function pointer can be used to invoke the function it points to and pass it arguments just like a normal function call. Such an invocation is also known as an "indirect" call, because the function is being invoked indirectly through a variable instead of directly through a fixed name or address. Function pointers can be used to simplify code by providing a simple way to select a function to execute based on run-time values.
Pointer = That hold the address of a variable or means simple memory.
As same like pointer , function pointer that hold the address of a function.
Syntax :
return type (*fp) (argument);
Example:
void f1()
{
printf("in function f1");
}
int main()
{
/* declaring a function pointer
* argument void
* return type is also void
*/
void (*fun_ptr) (void);
fun_pt= f1(); // fun_pthold the address of f1
(*fun_pt)(); // calling a function f1
}
I'm trying to use a separate function to input data using scanf() (outside of main). This new function is supposed to print a line and then receive input from the user. However something appears to be going awry between the scanf in the function and the printf() function in the main that I am testing it with.
I believe that I am receiving a pointer from the function but certain compiler warning are making me wonder if my assumption about the pointer is even correct.
I am confused by the output of this code:
#include <stdio.h>
void set_Info(void);
int main()
{
int scanNum = 0;
set_Info();
printf("%d", &scanNum);
return 0;
}
void set_Info(void) /* start of function definition */
{
int scanNum;
printf("Scan test, enter a number");
scanf("%d",&scanNum);
}
If I provide a number, say 2, the result of the printf statement in the main() is:
2665560
Now, in so far as I am able to tell that output appears to me like a memory address so what i attempted to do to fix that is dereference the pointer in main like so :
int scanNum = 0;
int scanNumHolder;
set_Info();
scanNumHolder = *scanNum;
printf("%d", &scanNumHolder);
I believe that this code makes scanNum variable to become assigned to the dereferenced value of scanNum. However I get the same output as above when I do this. Which leads me to believe one of two things. Either that I am not correctly dereferencing scanNum, or that scanNum is not in fact a pointer at all in this situation.
The most common error I receive from the compiler is:
error: invalid type argument of unary ‘*’ (have ‘int’)
Which makes sense, I suppose, if I'm attempting to treat an int value as a pointer.
If it is the case that scanNum is not being dereferenced correctly, how can I achieve this?
Thank you for the help
*Update
Thanks for the help.
Just to recap
My set_info function needs to be passed an address parameter. The reason an address parameter has to be used is because the local memory of a function is erased after the function call ends. So in order to do work a variable declared in the main function, I pass the address of the variable in question so that when the function ends the changes are not lost.
Inside the main function, when set_info is called with &scanNum as the argument, it passes a reference tp the variable so that it can be assigned the value generated by the scanf statement in the function.
I realize that what I was doing wrong as correctly pointed out by the awesome people of SO, is that I am trying to call set_info like it returns a value but in fact changes the variable like I actually want.
Thanks again for the help!
This function:
void set_Info(void)
{
int scanNum;
scanf("%d", &scanNum);
}
reads the integral number from the standard input and stores it into scanNum variable, which is local variable with automatic storage duration that exists only within the scope of this function.
And the body of your main:
int scanNum = 0;
set_Info();
printf("%d", &scanNum);
defines a local variable called scanNum, then calls a set_Info() function which doesn't affect scanNum defined in main in any way and then it prints the address of scanNum variable.
This is what you are trying to do:
void set_Info(int* num)
{
// read an integer and store it into int that num points to:
scanf("%d", num);
}
int main()
{
int scanNum = 0;
// pass the address of scanNum to set_Info function so that
// changes to scanNum are visible in the body of main as well:
set_Info(&scanNum);
printf("%d", scanNum);
return 0;
}
I also recommend you spend more time reading some book with C basics before you'll continue programming :)
I would pass in the variable into your set_Info function, so that it knows where to save the data. This would then allow you to scan multiple values, and you would simple increment the pointer. Be sure to pass the variable address into set_Info() using &variableName, since that function expects a pointer
#include <stdio.h>
void set_Info(int *pScanNum);
int main()
{
int scanNum = 0;
set_Info(&scanNum);
printf("%d", scanNum);
return 0;
}
//Pass in the pointer to scanNum
void set_Info(int *pScanNum)
{
printf("Scan test, enter a number");
scanf("%d",pScanNum);
}
Get rid of your ampersand! Printf wants an integer not a pointer.
printf("%d", scanNum);
And as liho said, you need to return scanNum from set_info so you can get at it outside of the function.
int scanNum = set_Info();
Just started working on a c project. Need help with passing function pointers/macro functions/etc. I'm a php & python OO guy, but new to c. I tried to generalize the example for this post. I have a main.c with a lib for the Axon microcontroller I'm working with. Works like a charm with everything in main.c. I need to move some of the functionality out of main to more organized lib files as my code grows. The base microcontroller lib creates a macro function that allows me to send data to the microcontroller to make a servo move left or right. I now need to create a servo specific file (HS-422.c) that will will allow me to pass references/pointers(?) to a generic function that will execute for each servo to ease on code duplication.
Keep in mind I'm only focused on passing macros/functions/variable references to other functions and have them called / set. The other basics of c I understand. I must have tried a 100 different ways to make this work today with no luck. So just wrote a simplified version hoping you might get an idea of what I'm attempting.
Thank you for your help!
/*
* main.h
* I'm trying to make a pointer or reference to the macro.
* The original file had:
* #define servo1(position) servo(PORTE,2,position);
*/
// servo is a macro defined in another microcontroller file
#define (void)(*servo1)(position) servo(PORTE,2,position);
#define (void)(*servo2)(position) servo(PORTE,3,position);
/* main.c */
// init main functions
void servo_scan(void);
// init vars
int servo1_location = 0;
int servo2_location = 0;
int main(void)
{
for(;;)
{
servo_turn();
}
}
// get the servos to turn
void servo_turn(void)
{
turn_servo( *servo1, &servo1_location, 200);
turn_servo( *servo2, &servo2_location, 950);
}
/* HS-422.c */
void turn_servo(void (*servo)(int position), int ¤tLocation, int newLocation)
{
// turning
for(uint16_t i=¤tLocation; i<newLocation; i=i+10)
{
// turn servo
// hoping the specifc passed servo# pointer gets called
*servo(i);
// set value by reference to origional servo#_location var. making sure.
¤tLocation = i;
// pause
delay_ms(20);
}
}
It's not really clear to me exactly what you're trying to achieve, but what is clear is that you don't really understand the concept of pointers/references in C - so I'll try to clarify, and hopefully that will help you implement what you need.
Firstly, there is no such thing as a "reference" in C. The only alternative to passing by value is to pass a pointer. A pointer is basically just a memory address, and you can get a pointer (memory address) to a variable using the & (address of) operator. When passing a pointer variable to a function, you do something like the following:
Given a function which takes a pointer:
int foo(int* pointer);
You would pass the memory address of an int variable to this function like so:
int x = 10;
foo(&x);
So right off the bat, you can see that your function definition above is wrong:
void turn_servo(void (*servo)(int position), int ¤tLocation, int newLocation);
This is simply a syntax error. It will not compile because of the int ¤tLocation. The & operator is used to take the address of a variable. It can't be used in a function parameter. If you want a "reference" to currentLocation, you need to pass in a pointer, so your function parameters should be written as:
void turn_servo(void (*servo)(int position), int* currentLocation, int newLocation);
Secondly, when you want to modify the value pointed to by the currentLocation pointer, you need to use the * operator to dereference the pointer. So, the line where you set currentLocation is not correct. What you want to say is:
// set value by to origional servo#_location var. making sure.
*currentLocation = i;
And of course, the line:
for(uint16_t i=¤tLocation; i<newLocation; i=i+10)
should be:
for(uint16_t i= *currentLocation; i<newLocation; i=i+10)
Note that in your original code you use the & operator in both cases, which takes the address of a variable. Since currentLocation is already a memory address, this would result in taking the address of an address, also known as a pointer-to-a-pointer, which is certainly not what you want here.
Finally, the phrase "pointer or reference to the macro" is completely nonsensical. A macro is not a function. It is more like a meta-function: essentially it is a template used by the C preprocessor to generate further source code. The C preprocessor is invoked before the compilation phase, and basically acts as a find/replace mechanism in the source code. You can't have a pointer to a macro, because for all intents and purposes macros don't even exist in the compilation phase. They are only meaningful to the preprocessor.
There may be more here, but ultimately you seem to have a fundamental misunderstanding of pointers (as well as macros) in C, and short of providing a complete tutorial, the best I can do is point out the syntax problems. I highly recommend you read a good introductory book to C, which will certainly go over pointers, macros, and functions.
I have picked the main point of your code and have this code below.
You may want to modify your #define in your original code.
Please see the code below: (you can also run this)
void myFunc(int pos);
void myFunc2(int pos);
int main (int argc, const char * argv[]) {
typedef void (*pFunc)(int);
pFunc pfArr[2];
pfArr[0] = &myFunc;
pfArr[1] = &myFunc2;
int x = 3;
int newLoc = 4;
turn_servo(pfArr[1], x, newLoc);
turn_servo(pfArr[0], x, newLoc);
return 0;
}
void turn_servo(void (*servo)(int position), int currentLocation, int newLocation)
{
printf("\nturn_servo starts");
printf("\nturn_servo currentLocation: %d", currentLocation);
printf("\nturn_servo newLocation: %d", newLocation);
servo(1);
}
void myFunc(int pos)
{
printf("\nmyFunc starts");
printf("\nmyFunc pos: %d", pos);
}
void myFunc2(int pos)
{
printf("\nmyFunc2 starts");
printf("\nmyFunc2 pos: %d", pos);
}
Your turn_servo() function will now accept two functions as parameter (either myFunc() or myFunc2()).
Just get the main point of this code and apply it. Hope this will help.