So say I have a basic struct with just a couple of values:
struct my_struct {
int val1;
int val2;
}
and I want to pass it to a function
int test_the_struct(struct my_struct *s);
and then inside that function I check for NULL and returns an error code, but I want it to continue if an empty struct is passed instead. For example:
struct my_struct *test_struct = (struct test_struct *) calloc(1, sizeof(struct test_struct));
test_the_struct(NULL); //this should fail
test_the_struct(test_struct); //this should not fail
How could I differentiate between the two? In this situation, I CANNOT alter the structure of my_struct
If I understand you correctly, you just don't have a problem.
Just check the pointer against NULL and you are fine.
int test_the_struct(struct my_struct *s)
{
if (s) { // or if (s != NULL) or whatever you want to express it...
return s->val1 + s->val2;
} else {
return 42;
}
}
If you call it with your test_struct, both values are 0. There is nothing wrong or special about it.
To find if a pointer s is null you can use
if (s) {
/* not null */
} else {
/* is null */
}
A pointer to an "empty" struct is not null.
design your function as belows
int test_the_struct(void *ptr)
{
if (ptr == NULL)
return -1; //error
else
return 0;
}
Related
I am reading the script on the implementation of malloc (first-fit), and I am a little confused about the value assignment of metadata structure. Could anyone give some explanations why the malloc returns flag_block->ptr (as a pointer to the allocated memory)? As far as I can see, there is no specific assignment to it.
typedef struct _metadata {
size_t size;
char free;
struct _metadata* next;
struct _metadata* prev;
char ptr[];
} metadata;
metadata* flag_block = NULL;
void *malloc(size_t size)
{
if (size==0) {
return NULL;
}
if (flag_block == NULL) {
flag_block = sbrk(size);
sbrk(sizeof(metadata));
if (flag_block == (void *)-1) {
return NULL;
}
flag_block->free = 0;
flag_block->next=NULL;
flag_block->prev=NULL;
flag_block->size = size;
return flag_block->ptr;
} else {
/*
....
*/
}
}
The ptr is called a flexible array member; it's an array without a size, and can only appear at the end of a struct.
So basically this:
return flag_block->ptr;
is equivalent to
return &flag_block->ptr[0];
So it's returning the address of the first byte after the rest of the members in the struct.
I have a fight game between 4 Magicians and 1 Demon in C.
Each of them have 3 attributes :
NAME
PV(Life points)
PM(Magic points)
I had to create a structure for Magician and Demon so i wrote :
struct Magician{
char name_magician[20];
int pm;
int pv;
};
struct Demon{
char name_demon[20];
int pv;
int pm;
};
typedef struct Magician magician;
typedef struct Demon demon;
Now:
How can i create a function that create a Demon?
And a function to create a group of 4 Magicians ?
What i tried in main function basically the simple :
demon d1;
d1.name_demon="demonx123";
d1.pv=15;
d1.pm=20;
Returning a single structure from a function is easy: You do it just like any other function returning a value:
demon create_demon(void)
{
demon d;
// Initialize the demon
return d;
}
Returning an array of multiple structures is a little harder, but just like for returning a single structure is the same as returning any value, returning an array of structures is exactly the same as returning an array of any other value. This can be done either by allocating on the heap, and returning a pointer. Or by passing a pointer to the first element as an argument to the function.
To make group of Magician, you can use array of Magician structure.
Something like...
> struct Magician m[4];
Use this statement in a function.
This will create you 4 members of Magician.Now you can initialize them as you are doing for demon.
struct Magician *m = malloc (sizeof(struct Magician)*NumOfMagitians);
And return the pointer
This way you can easily create your demons.
struct demon *createDemon(char *name, int pv, int pm){
struct demon *tmp = malloc(sizeof(struct demon));
if (tmp == NULL || sizeof(tmp->name) < strlen(name))
return NULL;
for (int i = 0; i < strlen(name); i++)
tmp->name[i] = name[i];
tmp->pm = pm;
tmp->pv = pv;
return tmp;
}
And in case you wonder, this way you can remove it again.
void removeDemon(struct demon *dtr){
if (dtr != NULL){
free(dtr);
}
}
To make your structure a little less static you should however change
the way you initialize the name of your creature, like:
struct demon{
char *name;
int pv;
int pm;
};
This way you can allocate the space you need for your creatures name dynamically like:
struct demon *createDemon(char *name, int pv, int pm){
// Try to allocate demon structure. If fail return NULL
struct demon *tmp = malloc(sizeof(struct demon));
if (tmp == NULL)
return NULL;
// Try to allocate demon name. If fail, return NULL
tmp->name = malloc(strlen(name));
if (tmp->name == NULL) {
free(tmp->name);
return NULL;
}
// Set Variables and return structure
tmp->name = name;
tmp->pm = pm;
tmp->pv = pv;
return tmp;
}
And you need to renew your removal function as well to remove the allocated space created for the name like:
void removeDemon(struct demon *dtr){
if (dtr != NULL){
free(dtr->name);
free(dtr);
}
}
I make the changes but
I can't add more than 2 nodes its will freez but if 1 or 2 node will work well what is the reason??? I gave_up
I can do nothing for that
This is my code till time
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
struct info{
int num;
char name[15];
struct info *next;
};
struct info *first,*current,*new_s;
int struct_num;
void add_struct(void);
int main(){
first=NULL;
add_struct();
puts("done");
add_struct();
puts("done");
add_struct();
puts("done");
return(0);
}
//struct add function
void add_struct(void){
new_s= malloc (sizeof(struct info));
if(!new_s){
puts("error");
exit (1);
}
if(first==NULL){
first = current= new_s;
first->next = NULL;
}else{
current=first;
while(current->next!=NULL){
current=current->next;
}
current->next=new_s;
current=new_s;
}
struct_num++;
}
The problem in your code is
if( first==NULL){
first->next=new_s;
if first is NULL, you should not dererefence it. It is logically wrong, and invokes undefined behaviour.
I think, what you want instead, is something like (pseudo-code)
if(first == NULL){
first = new_s;
first->next = NULL;
That said,
current->next=new_s;
current=new_s;
also looks problematic. The second statement there is wrong and not required, rather, you can add something like
current->next = new_s;
current->next->next = NULL;
Finally, your struct_num variable should be global, as per the current usage.
Note:
The recommended signature of main() is int main(void).
Please do not cast the return value of malloc() and family in C.
Always check for malloc() success before using the returned pointer.
Function add_struct is wrong
For example if first is equal to NULL then you may not write
first->next=new_s;
Take into account that there is no any sense to declare local variable of the function struct_num because it is always destroyed after exiting the function and moreover it even is not initialized in the function.
int struct_num;
If you need a count of nodes in the list then place it outside the function.
The function itself can look the following way
int struct_num;
int add_struct( void )
{
new_s = ( struct info * )malloc( sizeof( struct info ) );
if ( new_s == NULL ) return 0;
// initialize data members num and name of the allocated structure
new_s->next = NULL;
if ( first == NULL )
{
first = new_s;
}
else
{
current->next = new_s ;
}
current = new_s;
++struct_num;
return 1;
}
I have this code:
/* ... headers ... */
struct my_callback_struct {
int data;
int (*callback_func)(struct my_callback_struct *p, int data);
};
int reg(struct my_callback_struct *p, int data)
{
return 1;
}
void init(struct my_callback_struct *p)
{
p->callback_func = ®
}
int main ()
{
struct my_callback_struct *p;
init(p);
printf("%d", p->callback_func(p,12));
return 0;
}
so, basically I try to map p->callback_func with the function "reg". But when i compile it it says no errors but a segmention fault or something. I put a return of 1 just to check if it works...
What am i doing wrong?
You simply haven't allocated memory for your struct instance. Try something like
struct my_callback_struct s;
init(&s);
printf("%d", s.callback_func(p,12));
Or call malloc for your p before calling init.
You need to allocate your callback struct. The code as written is only a pointer to it. Two opens are:
struct my_callback_struct p; // Just "p", not "*p" which is a pointer
This allocates the struct on the stack. Its memory will no longer be allocated when the enclosing function returns. If you want it to have a longer lifetime you would most commonly use malloc() to dynamically allocate it:
struct my_callback_struct *p = (my_callback_struct*)malloc( sizeof( my_callback_struct ) );
if ( p == NULL ){
return -1; // Indicate failure to allocate
}
typedef struct student *std_ptr;
struct student
{
int number;
std_ptr next;
};
typedef std_ptr STACK;
create_stack(void)
{
STACK S;
S = (STACK) malloc( sizeof( struct student ) );
if(S == NULL) printf("out of space!");
return S;
}
void push(int x, STACK S)
{
std_ptr tmp;
tmp = (std_ptr) malloc(sizeof(struct student));
if(tmp == NULL) printf("out of space!");
else
{
tmp -> number = x;
tmp -> next = S -> next;
S -> next = tmp;
}
}
int main()
{
push(12058010,STACK S);
return 0;
}
Im trying to call function and I get error: expected expression before stack.I also tried to call the function like that
int main()
{
push(12058010,S);
return 0;
}
This time I get error: 'S' undeclared(first use in this function)
Thank you for your help!
Define the variable s by doing:
STACK s;
Initialise it:
s = create_stack();
Test whether the initialisation succeeded:
if (NULL == s)
{
return EXIT_FAILURE;
}
Use it by calling push() like this:
push(12058010, s);
All together this could look like this:
int main(void)
{
STACK s = create_stack(); /* This merges step 1 and 2. */
if (NULL == s)
{
return EXIT_FAILURE;
}
push(12058010, s);
return EXIT_SUCCES;
}
S is neither in the global scope nor in the scope of main().
I suspect you meant to write STACK S = create_stack(); as the first statement in main().
Don't forget to free the allocated memory as well.