I have a function called SemCreate that takes a name an int and a pointer as parameters. I want the pointer to point to a new struct and I want to return an int, 0 if it went okay.
int P1_SemCreate(char *name, unsigned int value, P1_Semaphore *sem){
USLOSS_Console("Create a semaphore\n");
if(!verifyKernel()) {
//USLOSS_Console("ERROR: Not currently in Kernel mode\n");
USLOSS_Halt(1);
}
if(numSems>= P1_MAXSEM){
//USLOSS_Console("ERROR: MAX semaphore already exist\n");
return -2;
}
if(name == NULL){
return -3;
}
interruptsOff();
int i;
for (i = 0; i < P1_MAXSEM; i++) {
if (semTable[i].inUse == 0) {
semTable[i].value = value;
semTable[i].list = NULL;
semTable[i].name = malloc(sizeof(char));
strcpy(semTable[i].name, name);
semTable[i].inUse = 1;
semaphore *temp = NULL;
temp = malloc(sizeof(semaphore));
temp->value = value;
temp->list = NULL;
temp->name = malloc(sizeof(char));
strcpy(temp->name, name);
*sem = temp;
break;
}
}
numSems++;
interruptsOn();
return 0;
}
Right now the pointer is fine within the function but once I return the pointer is null
EDIT: The array semTable is an array of semaphores
typedef struct semaphore{
int value;
char * name;
struct node *list;
int checkPoint;
int inUse;
}semaphore;
typedef struct PCB {
USLOSS_Context context;
int (*startFunc)(void *); /* Starting function */
void *startArg; /* Arg to starting function */
int pid;
int status;
int killedStatus;
int state;
int priority;
char name[50];
int parentPID;
int numOfChild;
int blockFlag;
struct sempahore *blockSem;
char *stack;
struct node *children;
struct node *zombiList;
int cpuTime;
int startTime;
struct semaphore *childSem;
} PCB;
typedef struct node {
PCB *pcb;
struct node *next;
} Node;
Your question is not perfectly clear as to what you are trying to do. So, this answer addresses the following general topics in hopes they will assist:
1) Passing the address of a struct via a function, changing the values of the struct members, and accessing changed values in calling function. (It is not the same as the one you show, but illustrates what you want to do.)
2) Creating instances and pointers to instances of a struct, then initializing.
3) Contains link to tutorial on self referencing structs. (as you are doing in your posted code)
typedef struct {//struct definition created in global space, typedef'ed
char line[80]; //to read in the line
int slot;
char type[20]; //long enough for any types listed
int position;
}SLOT;
int modifyStruct(SLOT *slot);//prototype of demonstration function
int main(void)
{
SLOT s;//create instance of SLOT local to main
int ret = modifyStruct(&s);pass address of SLOT instance to change member values
printf("Line: %s\n", s.line);//show changed values
printf("Slot: %d\n", s.slot);
printf("type: %s\n", s.type);
printf("position: %s\n", s.position);
return 0;
}
int modifyStruct(SLOT *slot)
{
strcpy(slot->line, "lineA");
slot->slot = 2;
strcpy(slot->type, "large");
slot->position = 20;
return 0;
}
EDIT - To address question in comment asking how to set a struct pointer to point to a struct.
First, it appears from viewing the code you have posted, that you are using self referencing structs. (i.e. a struct that contains a member that is a pointer instance to itself) Here is a link to a good tutorial dealing with Linked Lists in C, which use self referencing structs.
Regarding you comment: _I guess I should have made it more clear. P1_Semaphore is different to semaphore. I need P1_semaphore to point to the semaphore_.:
If P1_Semaphore is different than semaphore, then one should not be set to point to the address of the other. And your compiler will not let you do that anyway.
As I stated in the comments, a struct pointer should only point to a place in memory that contains an instance of that struct. For example consider the two structs A & B:
typedef struct {
int iNum;
float fNum;
char cStr[80];
}A;
A a, *pA; //create an instance, and pointer to an instance of A
typedef struct {
int iNum1;
int iNum2;
int iNum3;
}B;
B b, *pB; //create an instance, and pointer to an instance of B
A & B are obviously different, and will occupy a different size and shape in memory, so if the pointer to B, *pB was set to point to anything but B, it would be incorrect. It needs to point to B
Correct:
pA = &a //set pointer to A equal to the address of A
pB = &b //set pointer to B equal to the address of B
Incorrect:
pA = &b //set pointer to A equal to the address of B
pB = &a //set pointer to B equal to the address of A
(typical compiler error - Operands of = have types pointer to B and pointer to A)
In C/C++, all parameters are passed by value, not by reference. To get the struct pointer in parameter, you need to use pointer to pointer as the parameter. Like this:
int P1_SemCreate(char *name, unsigned int value, P1_Semaphore **sem){
...
*sem = temp;
...
}
Related
I'm getting the error for p->letter = 'A' and p->age = '9'. I don't know what is going wrong.
#include<stdio.h>
#include<stdlib.h>
struct player {
char letter;
int age;
};
typedef struct player *player_t;
int main (void)
{
player_t* p;
p = (player_t*)malloc(1 * sizeof(player_t));
if (p == NULL)
{
/* EDITED by #ahmedmasud removed original printf line for language */
printf("Unable to allocate\n");
return 1;
}
p->letter = 'A';
p->age = '9';
free(p);
return 0;
}
As many folks have pointed out you have a problem because in using typedef you went one step too far :-). Using typedef to recast types is meant for increasing clarity whereas the way you're using it decreases clarity.
Let me first show your example with the correct approach:
#include <stdio.h>
#include <stdlib.h>
struct player {
char letter;
int age;
};
/* typedef struct player *player_t; NOT NEEDED */
int main (void)
{
struct player *p;
p = malloc(sizeof(*p)); /* used *p for sizeof instead of struct player */
if (p == NULL)
{
fprintf(stderr, "Unable to allocate memory\n");
return 1;
}
p->letter = 'A';
p->age = '9';
free(p);
return 0;
}
When to use typedef foo_t bar_t
When it makes things clearer, e.g. stdint.h does this for integers. Say, you want a 32-bit unsigned int, you would use uint32_t which is appropriately typedef'd for various architectures to give you what you expect.
When NOT to use typedef struct foo foo_t
Pretty much all the time.
When it's OK to use typedef struct foo foo_t
Now for the reasons behind the changes, typedef struct foo foo_t is discouraged except when struct foo is opaque, typically when you are writing a C API where the structure is accessed through predefined access functions that have a longer life than internal structure.
Why use sizeof(*p) instead of sizeof(struct player) ?
In case, for some reason, you decide to change what *p is then all you have to do is change the declaration, and not worry that it's not going to get appropriately allocated.
This is an example of why you shouldn’t typedef a pointer.
player_t is a typedef for struct player *. You then define p as a player *, which means the full type of p is struct player **. The fact that you had a pointer hidden in a typedef ended up confusing you, and it can similarly confuse others who read your code.
Remove the pointer from the typedef and it will work as expected:
typedef struct player player_t;
You typedef
typedef struct player *player_t;
... so player_t is a type of pointer to struct player.
Then you define a variable:
player_t* p;
p is a pointer to pointer to struct player. Remove the *.
player_t* p; is not a pointer to struct player; it is a pointer to a pointer to struct player. Remove the * from the variable declaration and from the type cast before the call to malloc (you do not need that cast, anyway).
Change these two lines:
player_t* p;
p = (player_t*) malloc(1*sizeof(player_t));
into:
player_t p;
p = (player_t) malloc(1*sizeof(struct player));
p is of type player_t, which is already defined as a pointer to a player. No need for another * in its definition. Also, you need to allocate the size of the original struc, not the size of the pointer (sizeof(player_t) is the size in bytes of a pointer, not the size of the struct player).
Apart from what others pointed, Firstly typedef a pointer variable is not considered as good practice as hiding the * makes the code hard to read. Read Is it a good idea to typedef pointers?
Though if you want to typedef a pointer then do like below
typedef struct player {
char letter;
int age;
}player_t, *player_p; /* player_t is normal struct & player_p is pointer struct, here when someone see _p at the end of variable means it has * */
Next you need to allocate memory for player_p for e.g
player_p ptr = malloc(sizeof(struct player)); /* here don't take like "player_p *ptr" as player_p is already a pointer to struct */
if(ptr == NULL) {
/* error handling #TODO */
}
Later you can access structure member like
ptr->letter = 'A';
ptr->age = '9'; /* age is integer member, you may want to assign integer value directly like 57 instead of '9' */
And free the dynamically created memory by calling free().
free(ptr);
Sample code
typedef struct player {
char letter;
int age;
}player_t, *player_p;
int main(void) {
player_p ptr = malloc(sizeof(struct player));
if(ptr == NULL) {
/* error handling #TODO */
}
ptr->letter = 'A';
ptr->age = 50;
printf("%c .. %d \n",ptr->letter,ptr->age);
free(ptr);
return 0;
}
If condition inside the findset is not giving correct comparison. It is always shows not equal.
Where did I make a mistake?
#include<stdio.h>
struct node {
struct node *p;
int rank;
};
void makeset(struct node x) {
x.p = &x;
x.rank = 0;
}
void findset(struct node x) {
if (x.p == &x) {
printf("It worked bro\n");
}
}
int main() {
int nv, ne;
nv = 4;
ne = 5;
for (int i = 0; i < nv; ++i) {
struct node i;
makeset(i);
findset(i);
}
}
void findset(struct node x)
{
if (x.p == &x)
{
that x is a copy of the one passed in... x is always brand new and &x wont match any previous address.
Note that this is true not just of structs but all values...
int i = 3;
void f( int j)
{
// &j != &i
// j == i
// j and I have the same value, but different address
}
int main()
{
f(i);
}
There is no way your code will ever work. You ignore the fact that C uses pass by value -- meaning that when you pass a stuct node as a parameter to your function, (e.g. void makeset(struct node x)) the function receives a copy of the struct with its very own (and very different) address than the original struct in main().
So when you pass your struct to void findset(struct node x), there is no way if (x.p == &x) will ever test true -- because there is no requirement that the address of the copy of x received by void findset(struct node x) and stored in p is the same address as the copy of x that got passed to void makeset(struct node x).
Your second problem is your declare the same struct i 4 times in:
for (int i = 0; i < nv; ++i)
{
struct node i;
makeset(i);
findset(i);
}
You already have a variable i declared in your for loop. When you make the declaration struct node i;, you are not creating struct node 0;, struct node 1; ..., you are simply creating struct node i; 4 times. (no variable can be named a number or begin with a number in C) The i in your struct node declaration shadows the loop counter declaration of i. Add the warning -Wshadow to your compile string as a standard part of your compiler warnings.
What you need to do is declare an array of struct node if your want to be able to fill your nodes separately. For the purpose of this example, you could declare a struct with the same name 4-times - but that is rather limited to the use within your for loop (as your struct is declared within the for loop block, it is destroyed (the stack memory released for reused) each and every iteration of the loop. To prevent that from occurring, you can declare an array of 4 struct node before you enter your loop, e.g.
#include <stdio.h>
#define NNODES 4 /* if you need a constant, define one */
...
int main (void) {
struct node nodes[NNODES] = {{ .p = NULL }};
Next, to have any chance of findset ever being able to compare the original address of the struct node you pass as a parameter, you must pass the address of the struct, instead of the struct itself. That way, even though the function receives a pointer to a struct node, the value contained is the original address of the struct from the calling function (main() here)
So you need to change both function declarations to:
void makeset (struct node *x)
and
void findset (struct node *x)
You will also need to use the -> operator to access the members instead of the '.' operator.
Putting all the pieces together, you could do something similar to the following:
#include <stdio.h>
#define NNODES 4 /* if you need a constant, define one */
struct node {
struct node *p;
int rank;
};
void makeset (struct node *x)
{
x->p = x;
x->rank = 0;
}
void findset (struct node *x)
{
if (x->p == x)
printf ("It worked bro\n");
}
int main (void) {
struct node nodes[NNODES] = {{ .p = NULL }};
for (int i = 0; i < NNODES; i++) {
makeset (&nodes[i]);
findset (&nodes[i]);
}
}
(note: how the address of each struct node is passed to each function in main(), e.g. makeset (&nodes[i]);)
Example Use/Output
$ ./bin/struct_ptr_addr
It worked bro
It worked bro
It worked bro
It worked bro
It works now bro...
If you did really intend to declare a single stuct node in your for loop that is created and destroyed each iteration, then it works the same for a single struct as well -- you still have to pass the address of the struct to each function, e.g.
#include <stdio.h>
#define NNODES 4 /* if you need a constant, define one */
struct node {
struct node *p;
int rank;
};
void makeset (struct node *x)
{
x->p = x;
x->rank = 0;
}
void findset (struct node *x)
{
if (x->p == x)
printf ("It worked bro\n");
}
int main (void) {
for (int i = 0; i < NNODES; i++) {
struct node somenode = { .p = NULL };
makeset (&somenode);
findset (&somenode);
}
}
(the output is the same)
Hopefully, you now understand that when you pass a variable as a parameter, the called function receives a copy of the variable holding the original value. And, if you want to pass the address of the variable, then you have to pass the address as a pointer to insure that that original address is available within the called function (and any changes made visible back in the caller).
As the other poster said, you're passing in the value instead of the actual variable. The solution here is one of the reasons pointers are so powerful, you can just pass the pointer for the actual variable you want to change. For example:
void foo(){
int i = 8;
bar(&i);
}
int bar(int* i){
return *i * 2;
}
That should work better for you
i am created a struct
typedef struct t{
int top;
int value;
}s;
and another structure
typedef struct y{
int top1;
s **p
}z;
z *p1;
created a block by malloc
p1 = (z*) malloc(sizeof(z));
p1->p = (s**) malloc(10 * sizeof(s));
I tried with indexing the s structured block by
p1->p[4]->top;
but i got error. is there a way to index pointer to pointer type in C
Address them with single pointer.
typedef struct y{
int top1;
s *p; //Single pointer only
}z;
z *p1;
p1 = malloc(sizeof(z)); //Don't cast...
p1->p = malloc(10 * sizeof(s));
//And then:
p1->p[4].top;
If you still want double pointers, then:
typedef struct y{
int top1;
s **p;
} z;
z *p1;
size_t i;
p1 = malloc(sizeof(z)); //Create z structure object
p1->p = malloc(10 * sizeof(*p1->p)); //Create array of pointers to objects
//Now fill that array with your objects
for (i = 0; i < 10; i++) {
p1->p[i] = malloc(sizeof(*p1->p[i]));
}
//Now access to property as:
p1->p[4]->top; //Do something.
The second option is less preferable but depends on you, because doing single mallocfor 10 objects in a row is more efficient than doing 10x times single object and 11th time for initializing base array of pointers.
In struct y{ ...; s **p }, member p represents a pointer to a pointer to structure s, and not a pointer to structure s.
So p1->p[4] is a pointer to an s, not an s itself, so you cannot access member top with accessor .. To get around the compiler error, you would have to use accessor ->, which dereferences the pointer value, but then you yield undefined behaviour at runtime, since the pointer value is not initialized.
To solve the problem, you could either change the data type of p to s *p (as suggested by #tilz0R), or you could adapt your code to actually deal with pointers to pointers:
typedef struct t{
int top;
int value;
}s;
typedef struct y{
int top1;
s **p;
}z;
z *p1;
int main() {
p1 = malloc(sizeof(z));
p1->p = malloc(10 * sizeof(s*));
for (int i=0; i<10; i++) {
p1->p[i] = malloc(sizeof(s));
}
p1->p[4]->top = 5;
}
Note that pointers to pointers are more complicated to handle, as you need an extra step/loop to initialize the pointers and to free them later on. So actually I'd prefer the s *p-way; But sometimes pointers to pointers are more appropriate, e.g. if particular slots of the array shall remain "empty"; then you could set the respective pointer to NULL, which would not be possible in an array of struct objects.
When the program runs at the char filePath[100]="/home/wind/software/eclipse/eclipse2/server_multiaccess/wrPro3" , I find the
socket number of the child socket which is used to communicate is changed
suddenly.I wonder why?
The result is just like the picture:
The result using watch in gdb
sockM is a head of a struct list, which I defined myself. I try to put the child struct on the struct list.
struct Sock{
int socket;
short int ifMain;
short int status;
FILE* fp; // Cannot be initialized here
long int filePoint;
char recvBuf[BUFSZ];
char sendBuf[BUFSZ];
char command[BUFSZ];
unsigned long int answer;
};
struct sockListEle{
struct Sock sock;
struct sockListEle* last;
struct sockListEle* next;
struct sockListEle* head;
struct sockListEle* end;
int sockNum;
};
int main(void) {
int mainS,childS;
struct sockaddr_in mainSock;
int on;
.....
.....
while(1){
FD_SET(mainS,&mainRead);
select(mainS+1,&mainRead,NULL,NULL,&timeout);
if(FD_ISSET(mainS,&mainRead)){
struct sockaddr_in childSock;
.....
struct sockListEle sockC;
sockC.sock.ifMain=0;
......
sockC.next = NULL;
sockM.end = &sockC;
sockM.sockNum++;
sockC.last->next = &sockC;
maxfdp = maxfdp > childS ? maxfdp:childS+1;
}
.....
.....
if(maxfdp > 0){
.....
temp = &sockM;
do{
temp = temp->next;
switch(temp->sock.status){
....
case LOOKFOR:
if(FD_ISSET(temp->sock.socket,&writeList)){
send(temp->sock.socket, temp->sock.sendBuf, BUFSZ, 0);
if(!strcmp(temp->sock.command+4, "ls")){
char filePath[100] =
"/home/wind/software/eclipse/"
"eclipse2/server_multiaccess/wrPro3";
......
}
break;
......
}
}while(temp->next != NULL)
}
return EXIT_SUCCESS;
}
Problem are these three lines:
struct sockListEle sockC;
sockM.end = &sockC;
sockC.last->next = &sockC;
They are to be found all three within the same while, within the same if. So: sockC is located on the stack and reused within each loop, so all your elems in your list in the end point to one and the same sockC all the time. And if you modify it (possibly by calling accept), you modify the only visible instance for all your list elements.
Instead, you need to allocate separate memory for each socket:
struct sockListEle* sockC = (struct sockListEle*) malloc(sizeof(struct sockListEle));
and assign the pointer directly (without address-of operator &). Do not forget to free the memory as soon as you do not need it any more, else you get a memory leak.
#include "stdafx.h"
#include <stdio.h>
struct s
{
char *st;
struct s *sp;
};
struct s *p1,*p2;
void swap(struct s *p1,struct s *p2);
int main()
{
int i;
struct s *p[3];
static struct s a[]={
{"abc",a+1},{"def",a+2},{"ghi",a}
};
for(i=0;i<3;i++)
{
p[i]=a[i].sp;
}
swap(*p,a);
printf("%s %s %s\n",p[0]->st,(*p)->st,(*p)->sp->st);
return 0;
}
void swap(struct s *p1,struct s *p2)
{
char *temp;
temp = p1->st;
p1->st = p2->st;
p2->st = temp;
}
This program outputs as abc,abc,ghi. My doubt is what does p[0]->st,(*p)->st,(*p)->sp->st outputs.we havent intialised st with abc or ghi.How does it outputs the string?
We havent intialised st with abc or ghi. How does it outputs the
string?
The value of the st member for each structure in the statically allocated array a is actually initialized through an initialization list. Writing
static struct s a[]={
{"abc",a+1},{"def",a+2},{"ghi",a}
};
has the same effective meaning after its execution as writing the following:
static struct s a[3];
a[0].st = "abc";
a[0].sp = a+1;
a[1].st = "def";
a[1].sp = a+2;
a[2].st = "ghi";
a[2].sp = a;
And what's effectively happened after both methods of initialization is you have a statically-allocated circular linked list of struct s, where the data-members of each node in the list (the st member) is pointing to a string literal like "abc", "def", etc. The sp data member is pointing to the next node in the linked list.
I haven't analysed all the statements, but assignment to ->st and ->sp happens here:
static struct s a[]={
{"abc",a+1},{"def",a+2},{"ghi",a}
};
the rest are games with pointers so the output is what you see. So, say:
the a array is created and initialized;
in the for loop the p array is also initialized;
noticing that sp recursively points to struct s instances, p and a have the same structure;
each elements of p is made point to a struct s instance taken from one of the elements of a.