Let's say I have the following I'm using to call a function:
Item dummy;
while (!QueueIsEmpty(pq))
DeQueue(pq, &dummy);
Is there a way to put the dummy parameter into the call itself? Something like:
while (!QueueIsEmpty(pq))
DeQueue(pq, &(Item)NULL);
It looks like the method dequeues an object and copies its value to the dummy variable. Where would you expect it to be copied without providing a place to copy it to?
Do you want to just throw it away and clear the queue this way?
If so I would expect that you have to pass it inside unless there is another method that just clears the queue without even copying it. Maybe some clear method.
This isn't valid C [AFAICT]
From my top comment, you might mean: DeQueue(pq,(Item *) NULL) or simply: DeQueue(pq, NULL)?
You're trying to create a compound literal, but it's being initialized from a [NULL] pointer.
Here's the test program I created:
#include <stdio.h>
typedef struct {
int x;
} Queue;
typedef struct {
int y;
int z;
} Item;
int
QueueIsEmpty(Queue * pq)
{
return 0;
}
void
DeQueue(Queue * pq, Item * item)
{
}
int
main(void)
{
Item dummy;
Queue *pq = NULL;
while (!QueueIsEmpty(pq))
DeQueue(pq, &dummy);
// Is there a way to put the dummy parameter into the call itself?
// Something like:
while (!QueueIsEmpty(pq))
DeQueue(pq, &(Item) NULL);
return 0;
}
Here's the output of gcc:
x.c:38:3: error: conversion to non-scalar type requested
Here's the output of clang:
x.c:38:16: error: used type 'Item' where arithmetic or pointer type is required
What you may have wanted is:
DeQueue(pq, &(Item) { 0 })
But, passing that is a bit of [too much] trickery.
Personally, I've never done something like that. I've always just passed down a NULL pointer.
If you do really want a "dummy" parameter, I'd do the Item dummy; thing [vs the compound literal]. It's actually faster because you don't add the overhead of the initialization.
To me, the compound literal is getting "too cute"
If the function requires the address of a valid object, you can pass in the address of a compound literal:
DeQueue(pq, &((Item){0}) );
Related
Is it safe to return a struct with array data member in C?
Something like
struct my_str {
int v[5];
};
struct my_str ret_stupid() {
struct my_str rval;
/*do something..*/
return rval;
}
I don't know why... I'm a bit puzzled. (I've tried and it does work). Is there some standard explaining how this operation actually is performed? I mean the mechanism of struct return and assignment too could be useful to understand better.
Is it safe to return a struct with array data member in C?
Yes.
struct are copied bit-wise. Bit-wise copying a struct that has an array as a member makes sure that the copy of struct has a copy of the array too.
Structures are a lot like arrays.
They can contain variables of any kind.
Their addresses will be sorted stacked as long as you leave no gaps or invoke the preprocessor directive #pragma pack
"Is it safe", depends of the code hiding there..
/do something../
But in general - yes. This is just a function of type struct my_str and has to return struct my_str
What the structure contains - doesn't matter. Still safe to use.
You can return a structure from a function without any problems. It's a well-defined part of the language. You can pass structures to functions as well - a structure is exactly the same as any built-in type for purposes of parameter passing, return values, and assignment.
Here's an example
#include <stdio.h>
int func(int x)
{
int r = x;
return r;
}
int main(void)
{
int x = 12;
int y = func(x);
printf("%d\n", y);
return 0;
}
If it weren't for the array member, the return would be an "rvalue", a value that is just a copy of the value that you have inside the return expression. If you have
struct toto {
double a;
};
struct toto g(void) {
struct toto retval = { 0.0 };
...
return retval;
}
int main(void) {
printf("%g\n", g().a);
}
The argument of the printf call sees a copy of the variable retval that is used inside the function. g().a calls the function and uses the .a field of the return value.
This return value is and
entity that is not an object but only lives because of its "value", called rvalue in the C jargon. It only can be found on the RHS of an assignment, thus the "r" in "rvalue".
The case that you are giving is actually specially treated, because a "value" is not sufficient for all use cases of the array. So this generates a so-called "object with temporary lifetime". This is needed because if you'd do ret_stupid().v[2] the [] operator wants to have a pointer, and a pointer can only point to an object, not a value.
These objects only "live" inside the expression that contains the function call, and even though they are not const qualified you are not allowed to modify them.
So all in all, this is a corner case of C, and you shouldn't abuse it.
might be it's silly question but not getting what is wrong in my code.
I am writing simple command parser in which it will initialize appropriate parameters and call appropriate functions related to command code.
Ex.
char buffer[]="1123,13,46";
In above line 1123 is command code and rest of two tokens are parameters. In parser it will first find command code form command table and if command found then it will initialize structure of that command with above parameters.
Currently in my code i am successfully fetching correct command from command table and call that command's functions but failed to initialize the parameters with above values (13 and 46 here).Always getting 0.
As per below code same thing i want in my command parser but little modification
typedef struct
{
void *fields[2];
}tmpStruct;
typedef struct
{
int x;
int y;
}myStruct;
tmpStruct tmp_struct;
myStruct *getParams(tmpStruct *t_struct)
{
myStruct *genericStruct = malloc(sizeof(myStruct));
//setup the order of the fields in the handler
t_struct->fields[0]=(void*)&genericStruct->x;
t_struct->fields[1]=(void*)&genericStruct->y;
return genericStruct;
}
void *fillValue(tmpStruct *t_struct)
{
void *genericStruct;
genericStruct = getParams(t_struct);
*((int*)t_struct->fields[0])=12;
*((int*)t_struct->fields[1])=13;
return genericStruct;
}
void pritValue(myStruct *my_struct)
{
printf("%d %d\n",my_struct->x,my_struct->y);
}
int main()
{
void *genericStruct;
genericStruct = fillValue(&tmp_struct);
pritValue(genericStruct);
return 0;
}
Please find my working source file here
And header file here
The problem is that you are casting function pointers to types of functions that take different parameter types. Trying to make calls to functions through pointers like that is undefined behavior. Although you could potentially get away with calls that are similar - say, return myStruct* in place of void* pointer (although it's still undefined behavior), there is no way you could cast a function that takes an int and a myStruct* to a function type that takes an int and a variable list of arguments.
Changing your functions to the correct signatures to match cmdTableStruct table fixes this problem:
void *setParams(paramHandler_type *pHandler);
int printParams(int commandType,... );
static cmdTableStruct cmdTable[]=
{
{ 1123,setParams,printParams },
//more command in same manner
};
Demo.
Of course now you need to handle parameters from the ... list individually using the functionality from the <stdarg.h> header.
Also, the way you dereference param handler when assigning values is incorrect - the index should be applied to paramValue, not to pHandler:
*((int*)pHandler->paramValue[j]) = (int)atoi(token);
At the moment I'm trying
void avg(everything)
But that gives me the error:
error: subscripted value is neither array nor pointer
And when I got this error earlier today it was because I wasn't passing a 2D array to the function properly. So I figure this is the same but I can't find the correct format to pass it in.
This is my typedef:
typedef struct structure
{
char names[13][9];
int scores[13][4];
float average[13];
char letter[13];
} stuff;
And this is my typedef array:
stuff everything[13];
In the function signature, you need to specify the type, not the specific name of a variable you want to pass in. Further, if you want to pass an array, you need to pass a pointer (you should probably be passing structs by pointers anyway, otherwise a copy of the data will be made each time you call the function). Hence you function should look like:
void avg(stuff* s);
However, C arrays also have no concept of length. Hence, you should always pass in the length of the array to the function:
void avg(stuff* s, size_t len);
You'd then call this as follows:
avg(everything, 13);
Also, if the function doesn't modify the data in any way, you should signify this by specifying that the parameter is const:
void avg(const stuff* s, size_t len);
A type introduced with typedef is an alias that can be used for a real type.
For example:
typedef struct some_struct { ... } some_type_name;
Now you can use some_type_name instead of struct some_struct.
So when declaring a function which takes a structure of this "type" you use the type like any other type:
void some_function(some_type_name var) { ... }
In some_function as defined above, you can use var like a normal structure variable.
To define a function taking an array (or a pointer) to this type, that's equally simple:
void some_function(some_type_name *pointer) { ... }
i need to pass an int or a string into a push function for a stack. normally i would just overload the function and have one that takes in a string parameter and one that takes in an int parameter so that the appropriate function would be called just based off of the parameters. i wrote the spots in comments where i would normally include the type. i just got stuck there.
void push(Stack *S, /* int or a string */ element)
{
/* If the stack is full, we cannot push an element into it as there is no space for it.*/
if(S->size == S->capacity)
{
printf("Stack is Full\n");
}
else
{
/* Push an element on the top of it and increase its size by one*/
if (/* element is an int*/)
S->elements[S->size++] = element;
else if (/* element is a string */)
S->charElements[S->size++] = element;
}
return;
}
This is a situation where you could use a union and that would automatically manage things for you:
typedef union {
int integer;
char* string;
} Item;
or if need type checking anyway, you could use a struct with type and union inside:
typedef enum { INTEGER, STRING } Type;
typedef struct
{
Type type;
union {
int integer;
char *string;
} value;
} Item;
If you have a compiler that already implements that part of C11, you could go with the new feature _Generic. clang, e.g, already implements this and for gcc and cousins there are ways to emulate that feature: P99
It works usually through macros, something like this
#define STRING_OR_INT(X) _Generic((X), int: my_int_function, char const*: my_str_function)(X)
There is no function overloading in c.
You could pass the type in as an argument, make the element parameter a pointer and then re-cast the pointer to the appropriate type.
You have to use the facility provided in the language only. I do not think that there is a way to check if a variable is string or int in C. moreover element can not save both string and int be careful here . So go for function overloading. Good luck
You can try it in this way
void push (Stack *S,void *element)
{
(*element) //access using dereferencing of pointer by converting it to int
element // incase of char array
}
//from calling enviroment
int i =10;
char *str="hello world"
push(S,&i) //in case of int pass address of int
push(S,str) // in case of char array
//old and auqHdr are data structures of type gblAuqEntry and auQ respectively
//I traverse through the list 'auqHdr' and when I match the element 'old', I need to remove it
removeAUfromNodeAUQ(&old, &auqHdr);
//Function implementation
static void removeAUfromNodeAUQ(gblAuqEntry *old, auQ *auqH)
{
auQ *auqPtr, *prev;
int found =0;
for (auqPtr = auqH; auqPtr; auqPtr = auqPtr->nxt)
{
if (something)
prev = auqPtr;
else
{
prev->nxt = old->nxt;
found = 1;
break;
}
}
I am trying to remove the element 'old' in the list 'auqHdr'.
The error I am getting is "declaration is incompatible with previous "removeAUfromNodeAUQ""
Can someone please point out what I am doing wrong here?
Thanks
If you call the function before declaring it, C implies a return type of int, not void.
You should add this declaration in the header or at the top of your file to address the problem:
static void removeAUfromNodeAUQ(gblAuqEntry *old, auQ *auqH);
Well, if your code is exactly as you posted, then this:
removeAUfromNodeAUQ(&old, &auqHdr);
Is not a function call, it is a function declaration. You then define it, but with a different signature. In that context you are forward declaring a function. C assumes a return type of int for you.