Access struct member by an argument of function in C - c

int f(){
struct NUMBER {
int A;
int B;
};
struct NUMBER *num = malloc(sizeof(struct NUMBER));
num->A = 1;
num->B = 2;
int x = num->B;
return x;
}
int main(){
int z = f();
printf("%d\n", z);
}
Obviously, ./a.out will show 2.
My question: Can I access struct member by an argument of function? i.e. f(A) return 1, and f(B) return 2. Thanks a lot.

Not at all elegant, but I think it shows you what you need to do/know.
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
struct NUMBER {
int A;
int B;
};
struct NUMBER extNumber = {1, 2};
int f(int offset) {
int iRet = -1;
if (offset == offsetof(struct NUMBER, A)) {
iRet = extNumber.A;
} else if (offset == offsetof(struct NUMBER, B)) {
iRet = extNumber.B;
}
return iRet;
}
int main (int argc, char **argv) {
struct NUMBER number;
int iVal;
iVal = f(offsetof(struct NUMBER, A));
printf ("A : %d\n", iVal);
iVal = f(offsetof(struct NUMBER, B));
printf ("B : %d\n", iVal);
}

Can I access struct member by an argument of function?
I think you are also assuming struct is not visible outside the function. Now if the person who wrote main does not have visibility into the function (say it is part of a library), then the answer is NO.
Otherwise if author of main can see internals of the function, then: Can someone come up with a fancy way to access struct member inside the function via function argument? Towards that lets think what does f(A) mean? Here, A is a name of struct member, so do you mean passing char A to f and translating that to struct member inside f [e.g. result = *(int *)num+(inchar-'A') where inchar is aninput parameter to the function of type char]. Similarly, one can imagine other ways.

As far as I understand your problem, the cleanest and most "C-like" solution is to pass a pointer to your struct to f(), where you populate it:
typedef struct _NUMBER
{
int A;
int B;
}
NUMBER;
void f (NUMBER* pvNumber)
{
pvNumber->A = 1;
pvNumber->B = 2;
return;
}
Call it like this:
int main ()
{
NUMBER vNumber;
int z;
f (&vNumber);
z = vNumber.A; // or vNumber.B
return 0;
}
So you don't select the desired member inside f(), but outside of it.

Yes. you need to define some way to access to member desired, this is usually done with constants, or an enum. As an aside, you should always check the pointer returned by malloc() before using it.
#define GET_A (0)
#define GET_B (1)
int f(int selector){
struct NUMBER {
int A;
int B;
};
int result;
struct NUMBER *num = malloc(sizeof(struct NUMBER));
if (!num)
return -1; // or some other error code...
num -> A = 1;
num -> B = 2;
switch(selector)
{
case GET_A: result = num->A; break;
case GET_B: result = num->B; break;
// etc... if you have more members in your struct.
default: result = -1; break; // some error code.
}
free(num)
return result;
}
int main(){
int z = f(GET_B);
printf( "%d\n" , f(GET_B));
}

Related

How can I use variable have different type as function input

I have several data structures which all contain a same data structure inside
struct numbers{
int num_a;
int num_b;
};
struct var_a{
numbers num;
//other variables
};
struct var_b{
numbers num;
//other variables
};
Now I wants to write a single function to access struct numbers in all these structures(use +1 in my example below for demonstration purpose).
One way is to use void pointer input and then cast to struct number inside the function:
void foo(void* p_input)
{
((numbers*)p_input)->num.num_a += 1;
}
int main()
{
var_a a;
var_b b;
foo(&a);
foo(&b);
return 0;
}
But this method requires struct numbers put at the top of structure var_a/var_b/var_c.
Another way is to use a macro instead of a function:
#define foo(type_t, input) \
do{ \
((type_t*)input)->num.num_a += 1; \
while(0)
int main()
{
var_a a;
var_b b;
foo(typeof(a), &a);
foo(typeof(a), &b);
return 0;
}
But since my actual operation is much more complex than num_a += 1, I prefer not to use a macro.
Is there any way I can use a function to achieve my requirement?
Below I have pseudo-code which uses typeof as the function input but I suppose it is not valid in C.
void foo(void* p_input, type_t input_type)
{
((input_type*)p_input)->num.num_a += 1;
}
int main()
{
var_a a;
var_b b;
foo(a, typeof(a));
foo(b, typeof(b));
return 0;
}

Add a parameter to a function pointer

I'm using a function pointer to delegate states in C.
// states
void state1(int first, int second) {
...
}
void state2(int first, int second) {
...
}
// state pointer
void (*current_state)(int, int);
// state logic
if (condition1) {
current_state = &state_1;
} else if (condition2) {
current_state = &state_2;
}
// do the thing
(*current_state)(1, 2);
Now I'm at a point where the given arguments no longer suffice, so there is a third argument needed. Since I don't want to change all states, I wondered if it is possible to pass a quasi constant parameter along with the pointer. Something like this:
void state3(int first, int second, int third) {
...
}
// state logic
...
else if (condition3) {
// calculate the constant third argument
int param3 = 0;
current_state = &state_3(int, int, param3);
}
I there a way to get this to work?
Well I'm not sure I'd recommend it but you could do this sort of thing:
#include <stdlib.h>
#include <stdio.h>
typedef int pfun();
int alice( int a, int b) { return b; }
int bob( int a, int b, int c) { return c; }
int main( )
{
pfun* f;
f = alice;
printf( "%d\n", f( 1, 2, 3));
f = bob;
printf( "%d\n", f( 1, 2, 3));
return EXIT_SUCCESS;
}
This compiles with
gcc -o funp -Wall funp.c
without warnings and runs correctly.
The point is that a function declaration like
int f();
Says that f is a function that returns an int, with unspecified arguments. The downside is that the compiler cannot check that the arguments are of the correct type.
You could pass a *void pointer and cast it to the concrete type in the state function. All state functions will have the same signature. Something like this:
// states
struct state1_args {
int first;
int second;
};
struct state2_args {
float first;
float second;
float third;
};
void state1(void* state_args) {
struct state1_args* args = (struct state1_args*)state_args;
use(args->first);
...
}
void state2(void* state_args) {
struct state2_args* args = (struct state2_args*)state_args;
use(args->third);
...
}
// state pointer
void (*current_state)(void*);
// state logic
if (condition1) {
current_state = &state_1;
current_state_args = &args_1;
} else if (condition2) {
current_state = &state_2;
current_state_args = &args_2;
}
// do the thing
(*current_state)(current_state_args);

Why do we need pointer to a structure pointer to change members value?

While for simple types (simple types: int, char..) we directly use pointers (their address) as an argument to a function to permanently change their value in the main program, can someone explain to me why for structures we need a pointer to a Structure pointer, and not just a pointer?
struct someStruct
{
int field1;
int field2;
}
void initializeFields(struct someStruct** foo)
{
//changing fields
}
//while
void initializeFields(struct someStruct* foo) //does not work ?
struct someStruct* foo is fine, you don't need struct someStruct** foo. Not sure where you got that idea from, but it's not correct.
To only change the members of the structure you don't need that. But to change the actual pointer to the structure you need to emulate pass by reference by using pointer to a pointer to the structure.
For example, to only change a member this is enough
void initializeFields(struct someStruct* foo)
{
foo->field1 = 1;
foo->field2 = 2;
}
int main(void)
{
struct someStruct bar;
initializeFields(&bar);
printf("field1 = %d\n", bar.field1);
printf("field2 = %d\n", bar.field2);
return 0;
}
But if you for example want to dynamically allocate the structure in the function you need to emulate pass by reference:
void initializeFields(struct someStruct** foo)
{
// The difference is this assignment
*foo = malloc(sizeof(struct someStruct));
(*foo)->field1 = 1;
(*foo)->field2 = 2;
}
int main(void)
{
struct someStruct* bar;
initializeFields(&bar);
printf("field1 = %d\n", bar->field1);
printf("field2 = %d\n", bar->field2);
return 0;
}
Two more examples to show the difference between pass by value and emulating pass by reference.
Consider the following program:
#include <stdio.h>
void foo(int y)
{
y = 5;
}
int main(void)
{
int x = 1;
printf("1: x = %d\n", x);
foo(x);
printf("2: x = %d\n", x);
return 0;
}
The above program will print
1: x = 1
2: x = 1
That is because a copy of the value in x is passed to the function foo. Modifying the local copy inside foo will not modify the original variable x inside main.
Now to emulate pass by reference:
#include <stdio.h>
void foo(int *y)
{
*y = 5;
}
int main(void)
{
int x = 1;
printf("1: x = %d\n", x);
foo(&x);
printf("2: x = %d\n", x);
return 0;
}
This program will print
1: x = 1
2: x = 5
This is because we don't change the pointer variable y inside the function foo, but we change the value of where it points, which happens to be the variable x in the main function.
There are very specific cases where you need pointer to a struct pointer (array of struct pointers, mostly).
Otherwise, a pointer to a struct is enough.
struct someStruct
{
int field1;
int field2;
}
void initializeFields(struct someStruct* foo)
{
foo->field1 = 42;
foo->field2 = -1;
}

Pass pointer to struct by reference in C

Take in mind the following piece of code:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int a;
int b;
int c;
}A;
A *test;
void init(A* a)
{
a->a = 3;
a->b = 2;
a->c = 1;
}
int main()
{
test = malloc(sizeof(A));
init(test);
printf("%d\n", test->a);
return 0;
}
It runs fine! Now imagine that I want to use the malloc function outside the main itself without returning a pointer to the struct. I would put malloc inside init and pass test adress. But this doesnt seem to work.
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int a;
int b;
int c;
}A;
A *test;
void init(A** a)
{
*a = malloc(sizeof(A));
*a->a = 3;
*a->b = 2;
*a->c = 1;
}
int main()
{
init(&test);
printf("%d\n", test->a);
return 0;
}
It keeps telling me that int a(or b/c) is not a member of the struct A when I use the pointer.
Your problem is operator precedence. The -> operator has higher precedence than the * (dereference) operator, so *a->a is read as if it is *(a->a). Change *a->a to (*a)->a:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int a;
int b;
int c;
}A;
A *test;
void init(A** a)
{
*a = malloc(sizeof(A));
(*a)->a = 3;
(*a)->b = 2;
(*a)->c = 1;
}
int main()
{
init(&test);
printf("%d\n", test->a);
return 0;
}
You must add parenthesis:
void init(A **a)
{
*a = malloc(sizeof(A)); // bad you don't verify the return of malloc
(*a)->a = 3;
(*a)->b = 2;
(*a)->c = 1;
}
But it's good practice to do this:
void init(A **a)
{
A *ret = malloc(sizeof *ret); // we want the size that is referenced by ret
if (ret != NULL) { // you should check the return of malloc
ret->a = 3;
ret->b = 2;
ret->c = 1;
}
*a = ret;
}
You need to write (*a)->a = 3; for reasons of precedence.
Even though it's not a direct answer to your question, since we're in the vicinity of initialization I'd like to point out that C11 gives you a nicer syntax to initialize structs:
void init(A **a)
{
A *ret = malloc(sizeof *ret); // we want the size that is referenced by ret
if (ret != NULL) { // you should check the return of malloc
*ret = (A) {3, 2, 1};
// or
*ret = (A) { .a = 3, .b = 2, .c = 1 };
}
*a = ret;
}
Another advantage is that any uninitialized members are zeroed.

returning multiple values from a function [duplicate]

This question already has answers here:
How do I return multiple values from a function in C?
(8 answers)
Closed 3 years ago.
Can anyone tell me how to return multiple values from a function?
Please elaborate with some example?
Your choices here are to either return a struct with elements of your liking, or make the function to handle the arguments with pointers.
/* method 1 */
struct Bar{
int x;
int y;
};
struct Bar funct();
struct Bar funct(){
struct Bar result;
result.x = 1;
result.y = 2;
return result;
}
/* method 2 */
void funct2(int *x, int *y);
void funct2(int *x, int *y){
/* dereferencing and setting */
*x = 1;
*y = 2;
}
int main(int argc, char* argv[]) {
struct Bar dunno = funct();
int x,y;
funct2(&x, &y);
// dunno.x == x
// dunno.y == y
return 0;
}
You can't do that directly. Your options are to wrap multiple values into a struct, or to pass them in as pointer arguments to the function.
e.g.
typedef struct blah
{
int a;
float b;
} blah_t;
blah_t my_func()
{
blah_t blah;
blah.a = 1;
blah.b = 2.0f;
return blah;
}
or:
void my_func(int *p_a, float *p_b)
{
*p_a = 1;
*p_b = 2.0f;
}
First of all, take a step back and ask why you need to return multiple values. If those values aren't somehow related to each other (either functionally or operationally), then you need to stop and rethink what you're doing.
If the various data items are part of a larger, composite data type (such as a mailing address, or a line item in a sales order, or some other type described by multiple attributes), then define a struct type to represent a single value of that composite type:
struct addr { // struct type to represent mailing address
char *name;
int streetNumber;
char *streetName;
char *unitNumber;
char *city;
char state[3];
int ZIP;
};
struct addr getAddressFor(char *name) {...}
struct point2D {
int x;
int y;
};
struct polygon2D {
size_t numPoints;
struct point2D *points;
};
struct point2D getOrigin(struct polygon2D poly) {...}
Do not define a struct to collect random items that aren't somehow related to each other; that's just going to cause confusion for you and anyone who has to maintain your code down the road.
If the data items are not functionally related, but are somehow operationally related (e.g. data plus a status flag plus metadata about the operation or items as part of a single input operation), then use multiple writable parameters. The most obvious examples are the *scanf() functions in the standard library. There are also the strtod() and strtol() functions, which convert a string representation of a number; they return the converted value, but they also write the first character that was not converted to a separate parameter:
char *str = "3.14159";
double value;
char *chk;
value = strtod(str, &chk);
if (!isspace(*chk) && *chk != 0)
printf("Non-numeric character found in %s\n", str);
You can combine these approaches; here's an example inspired by some work I'm currently doing:
typedef enum {SUCCESS, REQ_GARBLED, NO_DATA_OF_TYPE, EMPTY, ERROR} Status;
typedef struct bounds {...} Bounds;
tyepdef struct metadata {
size_t bytesRead;
size_t elementsRead;
size_t rows;
size_t cols;
} Metadata;
typedef struct elevations {
size_t numValues;
short *elevations;
} Elevations;
Elevations elevs;
Metadata meta;
Bounds b = ...; // set up search boundary
Status stat = getElevationsFor(b, &elevs, &meta);
The service that I request elevation data from returns a 1-d sequence of values; the dimensions of the array are returned as part of the metadata.
You can do it using structures:
#include <stdio.h>
struct dont { int x; double y; };
struct dont fred(void)
{
struct dont b;
b.x = 1;
b.y = 91.99919;
return b;
}
int main(int argc, char **argv)
{
struct dont look = fred();
printf("look.x = %d, look.y = %lf\n", look.x, look.y);
return 0;
}
You cannot return multiple values from a C function.
You can either
Return a data structure with multiple values, like a struct or an array.
Pass pointers to the function and modify the values of the pointers inside the function. You need to pass x number of pointers where x is the number of return values you need
To return multiple values from a function we should use a pointer. Here is an example through which you can understand it better
int* twoSum(int* nums, int numsSize, int target) {
int i,j,*a;
a=(int*)malloc(2*sizeof(int));
for(i=0;i<numsSize;i++)
for(j=i+1;j<numsSize;j++)
if(nums[i]+nums[j]==target)
{
a[0]=i;
a[1]=j;
return a;
}
}
I´m a beginner in C, so I don´t have experience with array, pointer, structure. To get more than one value from my function I just used a global variable.
Here is my code:
#include <stdio.h>
double calculateCharges( double hourCharges );
// Global variable for totalCharges-function and main-function interaction
double totalCharges = 0;
int main ( void ) {
double car1 = 0;
double car2 = 0;
double car3 = 0;
double totalHours = 0;
printf( "%s", "Hours parked for Car #1: ");
scanf( "%lf", &car1 );
printf( "%s", "Hours parked for Car #2: ");
scanf( "%lf", &car2 );
printf( "%s", "Hours parked for Car #3: ");
scanf( "%lf", &car3 );
totalHours = car1 + car2 + car3;
printf( "%s", "Car\tHours\tCharge\n");
printf( "#1\t%.1f\t%.2f\n", car1, calculateCharges( car1 ));
printf( "#2\t%.1f\t%.2f\n", car2, calculateCharges( car2 ));
printf( "#3\t%.1f\t%.2f\n", car3, calculateCharges( car3 ));
printf( "TOTAL\t%.1f\t%.2f\n", totalHours, totalCharges);
}
double calculateCharges( double hourCharges ) {
double charges = 0;
if( hourCharges <= 3.0 ) {
charges = 2;
} else if ( hourCharges >= 24.0) {
charges = 10.00;
} else {
charges = ((hourCharges - 3.0)*0.5) + 2.0;
}
totalCharges += charges;
return charges;
}
Method 1 is using array
Method 2 is using pointer
Method 3 is using structure

Resources