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 8 years ago.
Improve this question
If I have a function
int foo() {
/* stuff */
}
to which I want to send arguments (in spite the fact that it's a bad practice):
int main(void) {
int arg1 = 3;
int arg2 = 4;
foo(arg1, arg2);
return 0;
}
then, how can I refer to the arguments arg1 and arg2 inside foo()?
What's wrong with int foo(int arg1, int arg2);?
If you're unsure about the number of arguments you will be passing look into variadic functions.
This is not exactly what you want and is completely unportable but it illustrates
the principle. You probably have to adjust the offsets and the offsets will be different if the calling function (main in this case) has other variables on the stack.
And of course, if the target platform has a stack that grows in the other direction you'd have to change the loop to count down p instead.
#include <stdio.h>
int foo(void) {
int *p;
int a, b;
int i;
for (i = 0; i < 32; i++) {
p = (&i + i);
printf("i %d : p %p %d\n", i, p, *p);
}
a = *(&i + 11);
b = *(&i + 10);
printf("a %d\n", a);
printf("b %d\n", b);
return a + b;
}
int main(void) {
int a = 8;
int b = 2;
foo();
return 0;
}
And for the record, this kind of stuff is both fun and useful. In particular, it can be invaluable to know when debugging. So I think the question is a good one. That does not mean that this kind of thing should ever end up in any "production" code.
You can solve it by having a global state and a helper function:
static int foo_i, foo_j;
static void foo_setup(int i, int j) {
foo_i = i; foo_j = j;
}
int foo() {
return foo_i % foo_j;
}
int main() {
foo_setup(10,40);
printf("%d\n", foo());
}
To decide whether this is suitable for you, you must consider that this solution is non-reentrant. If you are using threads, you may need to synchronise the calls to foo_setup and foo. Similarly, if you will not call foo immediately after calling foo_setup, you need to carefully craft your code to not use code calling foo_setup, in between.
If you can use c++, you can pass the arguments through the constructor and define an operator() method for the struct.
Thank you for the suggestions. The solution I suggest for the problem I introduced is as follows:
static int helper(int argc, ...) {
unsigned *argv = (unsigned *) (void *)(&argc + 1);
switch (argc) {
case 0: /* do stuff */
case 1: /* do stuff with argv[0] */
case 2: /* do stuff with argv[0], argv[1] */
...
case n: /* do stuff with argv[0], argv[1], ..., argv[n] */
}
}
int goo(void) {
return helper(0);
}
int bar(int arg1) {
return helper(1, arg1);
}
int foo(int arg1, int arg2) {
return helper(2, arg1, arg2);
}
int main(void) {
int arg1 = 3;
int arg2 = 4;
return foo(arg1, arg2);
}
Related
I have many similar function calls dealing with one structure, but each call is using different field of structure.
Example:
typedef struct {
int i1;
int i2;
int i3;
} S;
functions to get structure fields (it would be better to avoid them):
int getFieldI1 (S *s){ return s->i1; }
int getFieldI2 (S *s){ return s->i2; }
int getFieldI3 (S *s){ return s->i3; }
function i have to call many times:
void doJob (int (*get_field_func)(S *)){
//some code
S s;
int v = get_field_func(&s);
//some code
}
i call doJob() this way:
doJob(&getFieldI1);
doJob(&getFieldI2);
doJob(&getFieldI3);
i would like to do like this:
doJob(i1);
doJob(i2);
doJob(i3);
is it possible in C?
option 1 - offsets
You can use memory offsets.
void doJob (int offset){
//some code
S s;
int v = *(&s+offset*sizeof(int));
//some code
}
You can call it like this:
doJob(0);//i1
doJob(1);//i2
doJob(2);//i3
As pointed out in the comments, the offsets are unsafe. You can create a check for this:
if(offset>2||offset<0){
//some kind of error
}
Also, this can only be used if the structure only contains integers(or elements of the same type, you would need to adjust it)(see comments).
If there are elements before s1, s2 and s3, you'll need to add the size of the elements(as padding, just add it);
option 2 - constants
Another option (that hasn't the mentioned problems) is to define constants/macros:
You'll just define them like this:
#define I1 &getFieldI1
#define I2 &getFieldI2
#define I3 &getFieldI3
and just call it using:
doJob(I1);
doJob(I2);
doJob(I3);
Just pass in a pointer to the field:
void doJob( int* fieldPointer )
{
assert( fieldPointer != NULL );
// Get the field value:
int v = *fieldPointer;
// Do something with the field value:
v += 10;
// Save the updated value back to the field:
*fieldPointer = v;
}
Usage:
S structInstance = ...
doJob( &structInstance.i1 );
doJob( &structInstance.i2 );
doJob( &structInstance.i3 );
How to pass structure field name to function?
In general, you cannot. A typical library coded in C does not show fields of internal struct to outside. In other words, a field name is only known to the compiler, and relevant to the current translation unit, and makes no sense at runtime.
Consider the following metaprogramming approach: write a metaprogram (in C or in some scripting language like Guile, awk, Python, etc...) generating your C code, and set up your build accordingly. That might mean to edit your Makefile, or configure your build automation tool.
This is usual practice since the previous century. Look into SWIG or RPCGEN as a famous example.
You might perhaps use preprocessor tricks, e.g. X-macros.
Unfortunately, C doesn't allow exactly what you need. But you can achieve a partial win with some code changes.
I have one and half solutions. For the first I propose a (simplified!) implementation, for the second I provide just an hint. Please, check if they can be acceptable for you.
Your example structure:
typedef struct {
int i1;
int i2;
int i3;
} S;
I would define an enum representing the specific field:
typedef enum
{
FIELD_ID_I1,
FIELD_ID_I2,
FIELD_ID_I3,
FIELD_ID_MAX
} FieldId_e;
Then I would add a field parameter in your general function, managing internally the correct field to be returned. Some smart error managing in case of wrong ID has to be done here. I just return -1 for brevity.
int getField (S *s, FieldId id)
{
int ret = -1;
switch(id)
{
case FIELD_ID_I1:
ret = s->i1;
break;
case FIELD_ID_I2:
ret = s->i2;
break;
case FIELD_ID_I3:
ret = s->i3;
break;
}
return ret;
}
Your doJob will become
void doJob (int (*get_field_func)(S *, FieldId), FieldId id){
//some code
S s;
int v = get_field_func(&s, id);
//some code
}
And final call will become this one. But probably (and it depends on your scenario) having a single general function will make possible to omit the function pointer, simplifying much the interface.
doJob(&getField, FIELD_ID_I1);
doJob(&getField, FIELD_ID_I2);
doJob(&getField, FIELD_ID_I3);
Just a short reference to another tricky solution that would require to play with pointers.
Do you know offsetof macro? (Wikipedia EN)
It evaluates to the offset (in bytes) of a given member within a
struct or union type, an expression of type size_t. The offsetof()
macro takes two parameters, the first being a structure name, and the
second being the name of a member within the structure.
In this case you could have something like
int getField (S *s, size_t offset);
doJob(&getField, offsetof(S, i1));
I failed to guess right types for i1/i2/i3, sorry. So I use auto keyword from c++:
#include <stdio.h>
typedef struct {
int i1;
int i2;
int i3;
} S;
int getFieldI1 (S *s){ return s->i1; }
int getFieldI2 (S *s){ return s->i2; }
int getFieldI3 (S *s){ return s->i3; }
void doJob (int (*get_field_func)(S *)){
//some code
S s = {1,2,3};
//S s;
int v = get_field_func(&s);
//some code
printf("got: %d\n", v);
}
int main() {
S s = {1,2,3};
auto i1 = getFieldI1;
auto i2 = getFieldI2;
auto i3 = getFieldI3;
doJob(i1);
doJob(i2);
doJob(i3);
}
Then
g++ 59503102.cxx -o 59503102 && ./59503102
as expected produces
got: 1
got: 2
got: 3
plain c version
#include <stdio.h>
typedef struct {
int i1;
int i2;
int i3;
} S;
int getFieldI1 (S *s){ return s->i1; }
int getFieldI2 (S *s){ return s->i2; }
int getFieldI3 (S *s){ return s->i3; }
void doJob (int (*get_field_func)(S *)){
//some code
S s = {1,2,3};
//S s;
int v = get_field_func(&s);
//some code
printf("got: %d\n", v);
}
int main() {
S s = {1,2,3};
int (*i1)(S *) = getFieldI1;
int (*i2)(S *) = getFieldI2;
int (*i3)(S *) = getFieldI3;
doJob(i1);
doJob(i2);
doJob(i3);
}
I attended an interview where this code was written and I had to predict the output of the code.
int foo() {
int a;
a = 5;
return a;
}
void main() {
int b;
b = foo();
printf ("The returned value is %d\n", b);
}
The answer was so obvious to me and I answered 5. But the interviewer said the answer is unpredictable since the function would have been popped from the stack after return. Could anyone kindly clarify me on this?
The code as you have presented it does not have the problem the interviewer asserted it does. This code would:
#include <stdio.h>
int * foo ( void ) {
int a = 5; /* as a local, a is allocated on "the stack" */
return &a; /* and will not be "alive" after foo exits */
} /* so this is "undefined behavior" */
int main ( void ) {
int b = *foo(); /* chances are "it will work", or seem to */
printf("b = %d\n", b); /* as we don't do anything which is likely */
return 0; /* to disturb the stack where it lies in repose */
} /* but as "UB" anything can happen */
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
I have been studying C programming from a book called "The Practice of Programming" by Kernighan and Pike. Based on the material in this book I have written a small program to sort an array of integers given on the command line.
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 30
char *progname;
int arr[MAXSIZE];
int icmp(int *, int *);
int main(int argc, char *argv[]) {
int i;
progname = argv[0];
if (argc == 1) {
fprintf(stderr, "usage: %s [int ...]\n", progname);
exit(1);
}
for (i = 0; argc > 1 && i < MAXSIZE; i++, argc--) {
arr[i] = atoi(argv[i+1]);
}
int n = i;
qsort(arr, n, sizeof(*arr), icmp);
for (i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
exit(0);
}
int icmp(int *p1, int *p2) {
int v1 = *p1;
int v2 = *p2;
if (v1 < v2) {
return -1;
} else if (v1 == v2) {
return 0;
} else {
return 1;
}
}
Yes, my little program seems to work and I am quite happy with it. However, my implementation differs from the one given in the book, which does not seem to sort integers correctly. The authors define icmp() as:
int icmp(const void *p1, const void *p2) {
int v1, v2;
v1 = *(int *) p1;
v2 = *(int *) p2;
if (v1 < v2) {
return -1;
} else if (v1 == v2) {
return 0;
} else {
return 1;
}
}
What's the deal? My version also throws a warning from gcc:
warning: passing argument 4 of 'qsort' from incompatible pointer type
But, the qsort with the correct pointer type is not correctly sorting my ints! Very confused here. If anyone can enlighten me I will be very grateful.
qsort comparison: why const void *?
If you check the prototype of qsort, you'll find:
void qsort (void* base, size_t num, size_t size,
int (*compar)(const void*,const void*));
The parameter type of the compar function is const void * as you noticed.
It's void * because qsort is supposed to sort generic type, not just int. You can sort array of double, array of string, array of struct, and so on.
It's const void * to avoid accidental changes to the data that the pointer is pointing to (within that compar function). This is just a typical safety measure of the keyword const.
I'm wondering something like this is possible:
// declaration
void func();
int main()
{
int ar[] = { 1, 2, 3 };
func(ar); // call with parameter
return 1;
}
void func() // no parameters
{
// do something
}
Can someone explain me this and especially how can I access ar in func()?
In C (not C++), a function declared as func() is treated as having an unspecified number of untyped parameters. A function with no parameters should be explicitly declared as func(void).
A hack would be to exploit the GCC calling convention.
For x86, parameters are pushed into stack. Local variables are also in the stack.
So
void func()
{
int local_var;
int *ar;
uintptr_t *ptr = &local_var;
ptr += sizeof(int *);
ar = (int *)ptr;
May give you the array address in ar in x86.
For x86_64, the first parameter is stored in rdi register.
void func()
{
uintptr_t *ptr;
int *ar;
asm (
"movq %%rdi, %0"
:"=r"(*ptr)
:
:"rdi");
ar = (int *)ptr;
May give you the array address in ar in x86_64.
I have not tested these code myself and you may be to fine tune the offsets yourself.
But I am just showing one possible hack.
If you want to use any function with no parameters with any return type, it should be declared as (In C)
return_type func(void). It is only generic way of function declaration.
But any how, for your question , it possible to access but not generic..Try this program...
#include<stdio.h>
int *p;
void func();
int main()
{
int ar[] = { 1, 2, 3 };
p=ar;
printf("In main %d\n",ar[0]);
func(ar); // call with parameter
printf("In main %d\n",ar[0]);
return 1;
}
void func() // no parameters
{
printf("In func %d \n",*p);
*p=20;
}
Even this program works fine, it is not generic way and also is undefined.
if you declare function like void func (void) ,it will not work.
You can't access ar in func(), since you dont have a reference to it in func().
It would be possible if ar would be a global var or you have a pointer on it.
So that you can do something with func(), you need to pass it the input data you'll work with.
First you must declare the function properly :
// declaration
void func(int []);
The define it :
void func( int a[] )
{
// do something
printf ("a[0] = %d\n", a[0]);
}
Full code :
#include <stdio.h>
// declaration
void func(int []);
int main()
{
int ar[] = { 1, 2, 3 };
func(ar); // call with parameter
return 1;
}
void func( int a[] )
{
// do something
printf ("a[0] = %d\n", a[0]);
}
This will display :
a[0] = 1
You can implement something like this.
void func(int *p, int n);
int main()
{
int ar[] = { 1, 2, 3 };
func(ar, sizeof (ar)/sizeof(ar[0]) ); // call with parameter
return 1;
}
void func(int *p, int n) // added 2 parameters
{
int i=0;
for (i=0; i<n; ++i){
printf ("%d ", p[i]);
}
}
I keep geeting a segfault in the main function. I create a pointer to a struct I created and I pass it's reference to another function which allocates and reallocates memory. Then accessing it in the main function (where it was originally defined) causes a segfault.
Here is my test code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct {
char desc[20];
int nr;
} Kap;
void read(Kap *k);
int main(void) {
Kap *k = NULL;
read(k);
printf("__%s %d\n", k[4].desc, k[4].nr);
return 0;
}
void read(Kap *k) {
int size = 3;
k = (Kap*) calloc(size, sizeof(Kap));
k[0].nr = 1;
k[1].nr = 2;
k[2].nr = 3;
strcpy(k[0].desc, "hello0");
strcpy(k[1].desc, "hello1");
strcpy(k[2].desc, "hello2");
size *= 2;
k = (Kap*) realloc(k, sizeof(Kap)*size);
if(k == NULL) {
printf("ERROR\n");
exit(EXIT_FAILURE);
}
k[3].nr = 4;
k[4].nr = 5;
k[5].nr = 6;
strcpy(k[3].desc, "hello3");
strcpy(k[4].desc, "hello4");
strcpy(k[5].desc, "hello5");
}
What am I doing wrong?
Here's a simplified version of the problem you are having:
#include <stdio.h>
void func(int x)
{
x = 10;
}
int main()
{
int x = 5;
printf("x = %d\n", x);
func(x);
printf("x = %d\n", x);
}
The same reason x does not change is the reason that k does not change in your program. A simple way to fix it is this:
Kap *read()
{
Kap *k = calloc(...);
...
k = realloc(k, ...);
...
return k;
}
int main()
{
Kap *k = read();
...
}
The problem is you're not passing the pointer back to main(). Try something like this instead:
Kap * read();
int main(void) {
Kap *k = read();
printf("__%s %d\n", k[4].desc, k[4].nr);
return 0;
}
Kap * read() {
... everything else you're already doing ...
return k;
}
The code you showed passes a pointer by value into read(). The subroutine can use that pointer (though it's kind of useless since its local copy is immediately changed), however changes made within read() do not bubble back to its caller.
My suggestion is one method of allowing read() to send the new pointer back up, and it's probably the right method to choose. Another method is to change read()s signature to be void read(Kap **);, where it will receive a pointer to a pointer -- allowing it to modify the caller's pointer (due to being passed by reference).