How to make so that a field points to its structure? - c

to sum up i have two structures, item and player, the player structure contains two item structure in its fields.
The item structure have a field that is a pointer to a player structure, this pointer must points to the player that owns this item. When i initialize the player whith new_player() i want to make so that the items points to the player being created inside the function.
To me it doesn't seems possible because the items will points to a structure created on the stack, once the structure is returned its items members points to freed memory. I made a few tests that seems to confirm this theory.
Code:
struct item
{
int power;
struct player* owner;
};
struct item new_item(int power, struct player* owner)
{
struct item an_item;
an_item.power = power;
an_item.owner = owner;
return an_item;
}
struct player
{
int age;
struct item item_1;
struct item item_2;
};
struct player new_player(int age)
{
struct player a_player;
a_player.age = age;
a_player.item_1 = new_item(1, &a_player);
a_player.item_2 = new_item(2, &a_player);
return a_player;
}
A solution to this could be to return a pointer to player with new_player() and to allocate it on the heap:
struct player* new_player(int age)
{
struct player* a_player = malloc(sizeof (struct player));
a_player->age = age;
a_player->item_1 = new_item(1, a_player);
a_player->item_2 = new_item(2, a_player);
return a_player;
}
Tests:
int main()
{
struct player* player_1 = new_player(77);
printf("Age of the player: %d.\n", player_1->age);
printf("Age of the player (from item_1): %d.\n", player_1->item_1.owner->age);
printf("Age of the player (from item_2): %d.\n", player_1->item_2.owner->age);
printf("Age of the player (from item_1 by owner): %d.\n",
player_1->item_1.owner->item_1.owner->age);
printf("Age of the player (from item_2 by owner): %d.\n",
player_1->item_2.owner->item_2.owner->age);
printf("Age of the player (from item_1 by owner to item_2): %d.\n",
player_1->item_1.owner->item_2.owner->age);
printf("Age of the player (from item_2 by owner to item_1): %d.\n",
player_1->item_2.owner->item_1.owner->age);
printf("Power of the first item: %d, power of the second item: %d.\n",
player_1->item_1.power, player_1->item_2.power);
printf("Power of the first item (from item_1): %d, power of the first item (from item_2): %d.\n",
player_1->item_1.owner->item_1.power, player_1->item_2.owner->item_1.power);
printf("Power of the second item (from item_1): %d, power of the second item (from item_2): %d.\n",
player_1->item_1.owner->item_2.power, player_1->item_2.owner->item_2.power);
free(player_1);
return 0;
}
Could some experimented C programmers give me advices on what is the best way to do this (or others ways i haven't thinked about)?

In the player struct you have, the items are parts of the player. So when you allocate the player on the heap, you can just set player pointer inside the items to the newly created player.
You are right that, if you create the player on the stack, this will not work, because after returning, the player object will be copied, including the pointers to the items (which then point to the "previous" location of the player on the stack).
Another solution, that is often used, is to allocate the player outside of the new_player function and pass it in as a pointer:
void new_item(struct item *i, int power, struct player *p) {
i->owner = p;
i->power = power;
}
void new_player(struct player *p, int age) {
p->age = age;
new_item(&p->item_1, 1, p);
new_item(&p->item_2, 2, p);
}
struct player p;
new_player(&p, 10);
This way you can decouple the allocation of your objects from the initialization. You could for example, have a big array of player objects that holds all players and is allocated just once. Then you initialize the player objects by passing in pointers to the objects in the array.
Or you could heap-allocate a player and initialize it with the same function.

Just as reference, a professional program design would involve the following:
Create one class for item and one class for player. Every class is handling the creation and deletion of one object of that class. Typically you would do this with dynamic memory allocation.
Hide the contents of the struct to the caller by implementing opaque type (private encapsulation). All access to struct members has to be done through setter/getter functions
The item constructor function would have an optional parameter "owner". If an item has no owner, then set it to NULL.
Implement const correctness where applicable. For example, an item should not be allowed to modify its owner.
The rare case of "two-directional ownership" requires a few more forward declarations.
You'd end up with something like this:
item.h
#ifndef ITEM_H
#define ITEM_H
#include "player.h"
#include <stdlib.h>
typedef struct item_t item_t;
typedef struct player_t player_t; // forward declaration needed to prevent linker errors
item_t* item_create (int power, const player_t* owner);
void item_delete (item_t* item);
#endif
item.c
#include "item.h"
struct item_t
{
int power;
const player_t* owner;
};
item_t* item_create (int power, const player_t* owner)
{
item_t* new_item = malloc(sizeof(*new_item));
if(new_item != NULL)
{
new_item->power = power;
new_item->owner = owner;
}
return new_item;
}
void item_delete (item_t* item)
{
free(item);
}
player.h
#ifndef PLAYER_H
#define PLAYER_H
#include "item.h"
#include <stdlib.h>
typedef struct player_t player_t;
typedef struct item_t item_t; // forward declaration needed to prevent linker errors
player_t* player_create (int age);
void player_delete (player_t* player);
#endif
player.c
#include "player.h"
struct player_t
{
int age;
struct item_t* item_1;
struct item_t* item_2;
};
player_t* player_create (int age)
{
player_t* new_player = malloc(sizeof(*new_player));
if(new_player != NULL)
{
new_player->age = age;
new_player->item_1 = item_create(1, new_player);
new_player->item_2 = item_create(2, new_player);
}
return new_player;
}
void player_delete (player_t* player)
{
item_delete(player->item_1);
item_delete(player->item_2);
free(player);
}

Apply the same principle to the new_item() function. It have to return a pointer to the struct allocated.
I would like to recommend you to provide another function, that will be responsible for freeing all theses pointers. It could be an destroy_player(struct player *player) that will free both items and the player itself.

Related

Making two objects in C more object-oriented

First, this is merely an academic question. I know C is not the job for doing OOP programming, but this is more of a learning exercise for a beginner learning what's possible and what's not (or perhaps, what might be possible but is not a good idea).
Let's take the following as a starting place, where I have two different objects but I want to give each of them the same two methods: create and print. I've omitted any error checking, freeing, etc. just to simplify matters:
#include <stdio.h>
#include <stdlib.h>
struct Person {
char* name;
int age;
};
struct Car {
char* make;
char* model;
int year;
};
struct Person* create_person(void)
{
struct Person *new = malloc(sizeof (struct Person));
return new;
}
void print_person(struct Person* person)
{
printf("<Person: %s (%d)>\n", person->name, person->age);
}
struct Car* create_car(void)
{
struct Car *new = malloc(sizeof (struct Car));
return new;
}
void print_car(struct Car* car)
{
printf("<Car: %s - %s (%d)>\n", car->make, car->model, car->year);
}
int main(void)
{
struct Car *car = create_car();
*car = (struct Car) {.make="Chevy", .model="Eldorado", .year=2015};
print_car(car);
struct Person *person = create_person();
*person = (struct Person) {.name="Tom", .age=30};
print_person(person);
}
I would think that the first part would be to group the 'methods' into the struct itself. So then we would have:
#include <stdio.h>
#include <stdlib.h>
struct Person {
char* name;
int age;
void (*print)(struct Person*);
};
struct Car {
char* make;
char* model;
int year;
void (*print)(struct Car*);
};
void print_car(struct Car* car);
void print_person(struct Person* person);
struct Person* create_person(void)
{
struct Person *new = malloc(sizeof (struct Person));
return new;
}
void print_person(struct Person* person)
{
printf("<Person: %s (%d)>\n", person->name, person->age);
}
struct Car* create_car(void)
{
struct Car *new = malloc(sizeof (struct Car));
return new;
}
void print_car(struct Car* car)
{
printf("<Car: %s - %s (%d)>\n", car->make, car->model, car->year);
}
int main(void)
{
struct Car *car = create_car();
*car = (struct Car) {.make="Chevy", .model="Eldorado", .year=2015, .print=print_car};
car->print(car);
struct Person *person = create_person();
*person = (struct Person) {.name="Tom", .age=30, .print=print_person};
person->print(person);
}
What would be the next step in making it "more OOP like"? Perhaps using preprocessor glue and generics? What would be an example of the most OOP-like that the two objects could become? Again, I know this isn't what C is meant for, but it's more a learning experience.
You could use approach applied by the Linux kernel.
The implementation of OOP is based using a composition for inheritance, and embedding interfaces into new classes.
The macro container_of lets easily alternate between a pointer to class and a pointer to one of its members. Usually an embedded object will be an interface of the class. To find more details about container_of macro see my answer to other but related question.
https://stackoverflow.com/a/66429587/4989451
This methodology was used to create a huge complex object oriented software, i.e. Linux kernel.
In the examples from the question, the Car and Person classes use an printing interface that we can call struct Printable. I strongly suggest to produce a fully initialized objects in create_... functions. Let it make a copy of all strings. Moreover, you should add destroy_... methods to release resources allocated by create_....
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#define container_of(ptr, type, member) \
(type*)(void*)((char*)ptr - offsetof(type, member))
struct Printable {
void (*print)(struct Printable*);
};
struct Person {
char* name;
int age;
struct Printable printable;
};
void print_person(struct Printable *printable) {
struct Person *p = container_of(printable, struct Person, printable);
printf("<Person: %s (%d)>\n", p->name, p->age);
}
struct Person *create_person(char *name, int age) {
struct Person *p = malloc(sizeof *p);
p->name = strdup(name);
p->age = age;
p->printable.print = print_person;
return p;
}
struct Car {
char* make;
char* model;
int year;
struct Printable printable;
};
void print_car(struct Printable *printable) {
struct Car *c = container_of(printable, struct Car, printable);
printf("<Car: %s - %s (%d)>\n", c->make, c->model, c->year);
}
struct Car *create_car(char *make, char *model, int year) {
struct Car *c = malloc(sizeof *c);
c->make = strdup(make);
c->model = strdup(model);
c->year = year;
c->printable.print = print_car;
return c;
}
void print(struct Printable *printable) {
printable->print(printable);
}
int main() {
struct Car *car = create_car("Chevy", "Eldorado", 2015);
struct Person *person = create_person("Tom", 30);
print(&car->printable);
print(&person->printable);
return 0;
}
produces output:
<Car: Chevy - Eldorado (2015)>
<Person: Tom (30)>
Note that function print() takes a pointer to the Printable interface. The function does not need to know anything about the original class. No preprocessor is used. All casts are done on "library" side, not on clients side. The library initializes the Printable interface, therefore it cannot be misused.
You can easily add other base classes or interfaces like i.e. RefCounted to solve memory management. The i-face would contain a pointer to destructor and refcount itself. Other examples are intrusive linked lists or binary trees.

Calling base function from derived

I took this tutorial example Inheritance and Polymorphism in C and because I've customized it for my exact requirements it's throwing an error when I try to call base function.
Question: Why does it fail in line 8 of employee.c and Possible resolution
((Employee *)self)->super.display(self); // Sementation fault: 11
Download Project
main.c
#include "person.h"
#include "employee.h"
#include <stdio.h>
int main() {
Person* person = newPerson("John Doe");
Employee* employee = newEmployee("Jane Doe", "Acme", 40000);
person->display(person); // displaying Person object
puts("------");
employee->display((Person*)employee); // displaying employee info
return 0;
}
Person.h
#ifndef _PERSON_H
#define _PERSON_H
#include <stdlib.h>
typedef struct Person Person;
struct Person {
char* name;
void (*display)(Person*);
};
Person* newPerson(char* name);
#endif
Person.c
#include "person.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
static void display(Person* const self) {
printf("Name: %s\n", self->name);
}
Person* newPerson(char* name) {
Person* person = malloc(sizeof(Person));
person->name = name;
person->display = display;
return person;
}
Employee.h
#include "person.h"
typedef struct Employee Employee;
struct Employee {
Person super;
char* company;
int salary;
void (*display)(Person*);
};
Employee* newEmployee(char* name, char* company, int salary);
Employee.c
#include "employee.h"
#include <string.h>
#include <stdio.h>
static void display(Person* const self) {
puts(((Employee*)self)->super.name); // works
// ((Employee *)self)->super.display(self); // Sementation fault: 11
printf("Company: %s\n", ((Employee *)self)->company);
printf("Salary: %d\n", ((Employee*)self)->salary);
}
Employee* newEmployee(char* name, char* company, int salary) {
Employee* employee = malloc(sizeof(Employee));
employee->super.name = name;
employee->company = company;
employee->salary = salary;
employee->display = display;
return employee;
}
Probably, for every class in the chain, starting with the base Person, you should make method implementations available under separate names:
Person.h
typedef struct _Person Person;
typedef struct _Person {
void* derived;
char* first;
char* last;
void (*display)(Person*);
} Person;
Person* newPerson(char* first, char* last);
void Person_display(Person *); // analogous to Person::display in C++
Person.c
Person* newPerson(char* first, char* last) {
Person* person = (Person*)malloc(sizeof(Person));
person->derived = person; // pointing to itself
person->first = first;
person->last = last;
person->display = Person_display; // Initializing interface for access to functions
return person;
}
Employee.h
void Employee_display(Person const *); // available to lower subclasses
And in Employee.c
static void display(Person* const self) {
Person_display(self); // calling the superclass implementation
Employee *employee = self->derived;
printf("Company: %s\n", employee->company);
printf("Salary: %d\n", employee->salary);
}
Person* newEmployee(char* first, char* last, char* company, int salary) {
Person* person = newPerson(first, last); // calling base class constructor
Employee* employee = malloc(sizeof(Employee));
person->derived = employee; // pointing to derived object
employee->company = company; // initialising derived class members
employee->salary = salary;
person->display = Employee_display; // Changing base class interface to access derived class functions
return person;
}
Note that this is consistent with usual C++ virtual method contracts: calling display() from the base class ctor resolves to the base class's implementation and the derived class's method is only available after the base class subobject has been fully constructed.
The problem was because embedded struct in Employee didn't have display function pointer initialized and pointed to a function
struct Employee {
Person super;
...
}
Solution: Change the embedded structure Person to pointer type and call newPerson for super
employee.h
typedef struct Employee Employee;
struct Employee {
Person *super; // change this pointer type
char* company;
int salary;
void (*display)(Person*);
};
Employee* newEmployee(char* name, char* company, int salary);
employee.c
static void display(Person* const self) {
((Employee*)self)->super->display(((Employee*)self)->super);
printf("Company: %s\n", ((Employee *)self)->company);
printf("Salary: %d\n", ((Employee*)self)->salary);
}
Employee* newEmployee(char* name, char* company, int salary) {
Employee* employee = malloc(sizeof(Employee));
employee->super = newPerson(name); // call constructor here
employee->company = company;
employee->salary = salary;
employee->display = display;
return employee;
}
What you're currently trying to do is this.
First, you define a 'parent' structure:
typedef struct _Person {
void* derived;
char* first;
char* last;
void (*display)(Person*);
} Person;
Next, you define a 'derived' structure:
typedef struct _Employee {
Person* super;
char* company;
int salary;
void (*display)(Person*);
} Employee;
And finally you cast one type to the other:
return (Person*)employee;
which is wrong. It takes memory allocated for the Employee struct and tries to interpret it as Person. In other words, regards super as derived, company as first and bit pattern in salary as last. I hope you realize that's not quite what you meant.
The Person subobject of your Employee is actually pointed-to by super. Of course you can return employee->super from newEmployee(), this will be a correct instance of Person, but this is really a Person, a concrete instance of Person. It's not polymorphic anymore, and the employee-specific part of the object will then be lost, unrecoverable, unreachable and leaked — there's no way to downcast Person to Employee.
You have two options.
Change the declaration of struct _Employee to
typedef struct _Employee {
Person super;
This way you have immediate up- and downcasts (simply cast Employee * to Person *, and vice versa). All the Person properties of an Employee will then be accessible via its super: employee->super.display = display (where the display being assigned is that static procedure defined in Employee.c; to access Employee-specific portion of the object, it needs to downcast it to Person).
The obvious caveat to this approach is some loss of type safety (given a pointer to Person you cannot tell whether it is a Person or an Employee; this can be worked around by explicitly defining a concrete type descriptor in the base class:
struct _Person {
enum { PERSON, EMPLOYEE, STRANGER, UNDERCOVER_AGENT } concreteClass;
Now you have a run-time type information, but you have limited the allowed set of subclasses to your Person which is not how polymorphic types are commonly implemented.)
Stick to the original design with void *derived pointing to concrete subclass-specific part of the object.
As a side note, your original idea with derived pointing to the struct itself in case it is an instance of Person is a rather elegant way to distinguish instantiable base classes from those abstract :) : by convention, abstract class's constructor sets derived to NULL and leaves it to the derived class's ctor to set that to proper value; and each virtual method first checks whether it is non-NULL and throws an exception otherwise.

When should a pointer to a structure should be use in a structure or not?

I'm wondering when I should use a pointer to a structure in a structure or not.
I clearly understand why we use a pointer to a structure in linked lists for example, but I'm facing an issue in another case.
For example:
#include <stdlib.h>
#include <string.h>
#define NICK_MAX_LENGTH 100
struct deck {
size_t nb_cards;
int *cards;
}
// Should I do :
struct player {
int id;
char nick[NICK_MAX_LENGTH];
struct deck *pl_deck;
}
struct player* my_function1() {
struct player *pl = malloc(sizeof(struct player));
pl->id = 1;
strcpy(pl->nick, "Paul")
pl->pl_deck = malloc(sizeof(struct deck));
pl->pl_deck->nb_cards = 3;
for (int i = 0; i < 3; ++i)
pl->pl_deck->cards[i] = i + 1;
return pl;
}
// .. or should I do :
struct player {
int id;
char nick[NICK_MAX_LENGTH];
struct deck pl_deck;
}
struct player* my_function2() {
struct player *pl = malloc(sizeof(struct player));
pl->id = 2;
strcpy(pl->nick, "Matt")
struct deck pl_deck;
pl_deck.nb_cards = 3
for (int i = 0; i < 3; ++i)
pl_deck.cards[i] = i + 1;
pl->pl_deck = pl_deck;
return pl;
}
Use a pointer if the lifetimes of the two structures need to be managed indepdendently. If you can have multiple players using the same deck, you need to use a pointer so they can both refer to it. Or if you need to be able to free the player while keeping their deck around, or vice versa, you should use a pointer.
On the other hand, if there's always a one-to-one correspondence between player and deck, you should nest the structures.
Both options should work provided you write the parts you have not uncovered correctly.
But note that your deck is a small struct with very little storage overhead and, moreover, is uniquely owned by a player so composition would probably be a more realistic option, to eliminate all the complexities of pointer management.
(As long as you don't plan to reuse the decks, of course.)

C - Creating a dynamic array of structs, struct members printing wrong values?

I am trying to create a dynamic array of players which I can add to during run time - however if I create 3 players with x-coords: 4,7 and 15, then try to print these values the output is: 0, 33, 20762704.
I am new to C and pointers and am struggling to work out where it is going wrong.
#include <stdio.h>
#include <stdlib.h>
// contains data of a player
struct player {
int posX;
int posY;
int gold;
};
// struct for creating a list of players of dynamic size
struct playerList {
struct player p;
struct playerList *next;
};
// add a new player to the list with given coords
struct playerList *make(int x, int y) {
struct playerList *new_player;
new_player = (struct playerList *)malloc(sizeof(struct playerList));
new_player->p.posX = x;
new_player->p.posY = y;
new_player->p.gold = 0;
new_player->next = NULL;
return new_player;
}
// add a player to the list
void addPlayer(struct playerList *list, int x, int y) {
if(list->next) {
addPlayer(list->next,x,y);
}
else {
list->next = make(x,y);
}}
int main() {
struct playerList *players = (struct playerList *)malloc(sizeof(struct playerList));
addPlayer(players, 4,3);
addPlayer(players, 7,7);
addPlayer(players,15,1);
printf("%d\n",players[0].p.posX);
printf("%d\n",players[1].p.posX);
printf("%d\n",players[2].p.posX);
return 0;
}
In order to add the first player to the list, you must pass a pointer-to-pointer-to-playerList to addPerson because the first node address will become the list address. Otherwise, you must return type *playerList and assign the return to your list variable back in the calling function. It is just as easy to pass the playerList ** parameter to your function and return a pointer to indicate success/failure as well as for convenience. e.g.:
/* add a player to the list */
playerList addPlayer (struct playerList **list, int x, int y) {
struct playerList *node = make (x, y);
if (!node) { /* validate new player created */
fprintf (stderr, "error: make player failed for (%d,%d).\n", x, y);
return NULL;
}
if (!*list) /* if first node, set list address to node & return */
return *list = node;
struct playerList *iter = *list; /* list pointer to iterate to end */
/* insert all other nodes at end */
for (; iter->next; iter = iter->next) {}
iter->next = node; /* add new player at end, return original *list */
return *list;
}
Then in main
addPlayer(&players, 4,3);
...
(note: the addPlayer is no longer recursive. As your list size grows, the additional resources needed for recursive calls can become significant, further, there is no need for a recursive call as the procedural iteration to the end of list to add a new player is straight forward.)
Look over the change and let me know if you have any additional questions. (note: I have not checked the remainder of your code for further errors)
In the list, you have a node that you are going to save some data on it, and it points to the next node too. So, you could define list structure to maintain the head of your list, and probably some other required information such length of the list or garbage handling or ...
For initialization you should set the length with zero and head pointer of list to NULL, these steps show the empty status of the list.
When you want to add to the list, you could add at the end of it, or at the head of it. In your program, you choose the second insertion policy, at the end. So, to add, you should traverse the list (all nodes), to find the last node, to add new node after that one. You should be aware of adding the new node when the list is empty, in this case you should update the head of your list.
For printing, there is a similar way, you should traverse the list and print the node information of that, until you reach the null pointer at the end of list.
After any allocation you should check the allocation success, if the pointer is not null, it was successful.
Another point, when you can handle adding the new node with using a simple loop, why you should use the recursive function? In this cases, it is better to use the loop.
The last point, dynamic allocation memory used commonly when the number of the list is specified in the run time, for example. It is a good point, to less memory allocation if you don't have to use. For instance, in the main you could define the list variable as a static variable, and send the address of that to the functions.
I tested the program, and its output was okay.
#include <stdio.h>
#include <stdlib.h>
// contains data of a player
struct player {
int posX;
int posY;
int gold;
};
// struct for creating a list of players of dynamic size
struct playerNode {
struct player p;
struct playerNode *next;
};
struct playerList {
struct playerNode *head;
int len;
// Add other required variables here
};
// add a new player to the list with given coords
struct playerNode *make(int x, int y) {
struct playerNode *new_player;
// you need to check memory allocation success
new_player = malloc(sizeof(struct playerNode));
new_player->p.posX = x;
new_player->p.posY = y;
new_player->p.gold = 0;
new_player->next = NULL;
return new_player;
}
// add a player to the list
void addPlayer(struct playerList *list, int x, int y) {
struct playerNode *player = list->head;
if(!player)
// you need to check memory allocation success
list->head = make(x, y);
else
{
while (player->next) {
player = player->next;
}
// you need to check memory allocation success
player->next = make(x, y);
}
list->len++;
}
void showPlayers(struct playerList *list) {
struct playerNode *player = list->head;
while (player) {
printf("%d\n", player->p.posX);
printf("%d\n", player->p.posY);
printf("%d\n", player->p.gold);
printf("--------------------\n");
player = player->next;
}
}
int main() {
struct playerList players;
players.len = 0;
players.head = NULL;
addPlayer(&players, 4, 3);
addPlayer(&players, 7, 7);
addPlayer(&players, 15, 1);
showPlayers(&players);
return 0;
}

Printing a struct in a struct in a linked list

I have a struct like this:
typedef struct stockItem {
char *componentType;
char *stockCode;
int numOfItems;
int price;
} stockItem;
// declaration
stockItem *stockItem_new(char *componentType, char *stockCode, int numOfItems, int price);
And a struct like this to store many stock items ( linked list )
typedef struct inventory {
struct stockItem item;
struct inventory *next;
}inventory;
These are both in different header file.
I have created the linked list, I want to print off certain bits of data, such:
void outputData(){
// This temporarily takes the location of the structs in the
// linked list as we cycle through them to the end
struct inventory *myInv = pFirstNode;
printf("Current Inventory\n\n");
// Until the ptr reaches a value of NULL for next we'll
// keep printing out values
while(myInv != NULL){
// HERE IS MY PROBLEM HOW DO I PRINT OFF THE COMPONENTTYPE FROM THIS
printf("%s\n\n", myInv->item->compnentType);
// Switch to the next struct in the list
myInv = myInv->next;
}
}
EDIT:
stockItem *stockItem_new(char *componentType, char *stockCode, int numOfItems, int price){
// creates a new duration for the song
stockItem *item = (stockItem*)malloc(sizeof(stockItem));
// assigns the attributes
item->componentType = componentType;
item->stockCode = stockCode;
item->numOfItems = numOfItems;
item->price = price;
// returns it
return item;
}
We don't see the rest of the code, but since you have stockItem_new returning a pointer, then this is wrong:
typedef struct inventory {
struct stockItem item; ///missing *!
struct inventory *next;
} inventory;
Instead, we need to declare it as:
typedef struct inventory {
struct stockItem *item;
struct inventory *next;
} inventory;
Then you can assign to the item with your stockItem_new function and your outputData will work as you expect.
Update:
In your stockItem_new, you are not making a copy of the contents of componentType, but just pointing to the same value. You either need to allocate a new buffer each time and pass into stockItem_new or take care of that with strdup
item->componentType = strdup(componentType);
This will allocate enough memory and copy the contents of componentType. You would need to do this for any strings you will be keeping in your struct (since only the address is copied!).

Resources