What is the best/fastest way ?
Struct of struct:
struct Sheet{
u8 status; // to check if empty ?
u8 reserve0;
u8 reserve1;
u8 reserve2;
struct words words[1024];
};
struct Book {
int id;
struct Sheet sheet[64];
};
In this case, how to check if the sheet table is empty or not ? I need to add a status for each sheet ?
or
Pointer table of struct
struct Sheet{
u8 reserve0;
u8 reserve1;
u8 reserve2;
struct words words[1024];
};
struct Book {
int id;
struct Sheet* sheet[64];
};
I don't need to use malloc since they are fixed table.
In the struct of struct, I can initialize by setting status but for pointer to struct, I can initialize with bookinstance.sheet[] = NULL or something like this.
I am pretty lost with pointers, struct and malloc. I come from Ruby...
To be clear:
I want not more than 64 sheet in my book instance. Maybe only 3 will be used or 64... But I want to be able to add them and check them with a number from 0 to 63.
To a certain extent it depend on what you mean by "faster".
How your code will interact with these elements will change that. In general; however, there are very few times you would likely see any significant effect of CPU time.
Note that in option 2 Book only allocates an array of pointers so you will have to add code (and overhead) to allocate Sheets for the pointers to point to.
The first option would seem cleaner as long as you are not intending on some Sheets to be shared among books.
Also, if you are copying books, option 2 would be faster since you would only be copying pointer rather then the entire Sheet struct.
Related
Consider the following code fragment:
struct data_t {
int data1;
int data2;
struct data_t *next;
size_t size;
int data3;
int data4;
};
int *ptr;
struct data_t data;
...
ptr = &data.data4;
Now using pointer, which is set to point to the last element in the structure, how can one use that pointer to access the first element in the structure (data1)?
Normally, what I would do in this case is back up the pointer by so many words to point to that element, but there is a problem. The pointer variable next in the middle of the structure has a varying size depending on the platform. If this is running on a 32-bit platform, then the pointer is 4 bytes while on a 64-bit platform, the pointer takes up 8 bytes. A similar issue happens with the size_t datatype as well.
Although not clear in the example, the structure is the header to a block of memory that is variable in size and is part of a linked list. AKA a free list in a memory allocator. Other than using some kind of an initialization that calculates the size of the pointer itself, is there a portable way of getting the address of the first element of the structure?
You can use offsetof to know how far a member is from the start of the structure. In this case:
struct data_t *p = (struct data_t *)( (char *)ptr - offsetof(struct data_t, data4) );
Obviously this requires you to know that the pointer is pointing at a data4 already, there's no way to autodetect that or anything. And, of course, it would be preferable to use a code design where you pass around the struct data * in the first place.
Is it possible to have two flexible-sized array within one structure ?
I know I can do something like below
struct A {
int countB;
struct B[0];
}
But my question is can we do something like below ?
struct A {
int countB;
struct B[0];
int countC;
struct C[0];
}
If yes, how would we get the offset of countC ?
If the above is very hard to implement, is there any other easy to tackle these kind of situations?
No, you are not allowed more than one flexible-size array per data structure:
6.7.2.1.16: As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member.
The reason why the flexible array member must be the last one is that otherwise it would be impossible to compute the offset (the number of bytes relative to the address of the initial member of the struct) for any member following the flexible array member.
In your case a work-around is possible, at the expense of storing an extra pointer before the flexible member, pointing to the location of C inside B:
struct A {
int countB;
int countC;
struct some_struct *C;
struct some_struct B[0];
};
When you allocate struct A, you need to allocate an additional size of countB+countC. Member C needs to be set to the address of B+countB.
On the project in my company I saw a couple of times people creating a struct that contains only one element.
the latest one is added, in this example ipAddr is another struct( a good explanation to the case when ipAddr is an array is given by 'Frerich Raabe' but unfortunately thats not the case here)
typedef struct
{
ipAddr ip;
} Record;
I guess if the code is changing and in its beginning this makes sense since more fields can be easily added and the code can be easily manipulated to support the new fields, but this is a project started a long time ago written according to a design so I dont think its the issue here.
Why would one create a struct of one field then?
I can think of a couple reasons:
In case more fields may be needed later. This is somewhat common.
To deliberately make the outer type incompatible with the inner type.
For an example of the second, imagine this:
typedef struct
{
char postal_code[12];
} Destination;
In this case, the Destination is fully specified by the postal code, yet this will let us define functions like this:
int deliver(const char* message, const Destination* to);
This way, no user can inadvertently call the function with the two arguments reversed, which they could easily do if they were both plain strings.
A common reason for a struct with just one field is that the single field is an array, and you'd like to be able to define functions returning such array values. Consider e.g.
typedef unsigned char ipAddr[4];
void f(ipAddr ip); /* OK */
ipAddr g(void); /* Compiler barfs: cannot return array. */
This can be resolved by introducing a struct with a single member of type ipAddr:
typedef unsigned char ipAddr[4];
typedef struct {
ipAddr ip;
} Record;
void f(Record ip); /* OK */
Record g(void); /* Also OK: structs can be returned by value. */
However, even passing arrays to functions is problematic: you don't actually pass the array, you pass a pointer (the type "decays" into a pointer). Imagine f declared above would need to create a copy of the given IP address:
typedef unsignd char ipAddr[4];
void f(ipAddr ip) {
ipAddr *a = malloc(sizeof(ip));
/* ... */
}
This only happens to work with 32bit builds because the size of a pointer is the same (4 bytes) as the size of an array of four unsigned char values. A 64bit build (or a differently sized array) would exhibit a bug, either allocating too much or too little memory. This happens because inside f, ip is of type unsigned char *, i.e.a pointer. A struct helps with this, since it doesn't decay.
Often stacks in C are dependent upon datatype used to declare them. For example,
int arr[5]; //creates an integer array of size 5 for stack use
char arr[5]; //creates a character array of size 5 for stack use
are both limited to holding integer and character datatypes respectively and presumes that the programmer knows what data is generated during the runtime. What if I want a stack which can hold any datatype?
I initially thought of implementing it as a union, but the approach is not only difficult but also flawed. Any other suggestions?
I would use a structure like this:
struct THolder
{
int dataType; // this is a value representing the type
void *val; // this is the value
};
Then use an array of THolder to store your values.
This is really just a variant of Pablo Santa Cruz' answer, but I think it looks neater:
typedef enum { integer, real, other } type_t;
typedef struct {
type_t type;
union {
int normal_int; /* valid when type == integer */
double large_float; /* valid when type == real */
void * other; /* valid when type == other */
} content;
} stack_data_t;
You still need to use some way to explicitly set the type of data stored in each element, there is no easy way around that.
You could look into preprocessor magic relying on the compiler-dependent typeof keyword to do that automagically, but that will probably not do anything but ruin the portability.
Some people have suggested a void* member. In addition to that solution I'd like to offer an alternative (assuming your stack is a linked list of heap-allocated structures):
struct stack_node
{
struct stack_node *next;
char data[];
};
The data[] is a C99 construct. data must be the last member; this takes advantage of the fact that we can stuff arbitrary quantities after the address of the struct. If you're using non-C99 compiler you might have to do some sketchy trick like declare it as data[0].
Then you can do something like this:
struct stack_node*
allocate_stack_node(size_t extra_size)
{
return malloc(sizeof(struct stack_node) + extra_size);
}
/* In some other function... */
struct stack_node *ptr = allocate_stack_node(sizeof(int));
int *p = (int*)ptr->data;
If this looks ugly and hacky, it is... But the advantage here is that you still get the generic goodness without introducing more indirection (thus slightly quicker access times for ptr->data than if it were void* pointing to a different location from the structure.)
Update: I'd also like to point out that the code sample I give may have problems if your machine happens to have different alignment requirements for int than char. This is meant as an illustrative example; YMMV.
You could use macros and a "container" type to reduce "type" from being per-element, to whole-container. (C99 code below)
#define GENERIC_STACK(name, type, typeid, elements) \
struct name##_stack { \
unsigned int TypeID; \
type Data[elements]; \
} name = { .TypeID = typeid }
Of course, your "TypeID" would have to allow every possible agreed-upon type you expect; might be a problem if you intend to use whole structs or other user-defined types.
I realize having a uniquely named struct type for every variable is odd and probably not useful... oops.
I created an library that works for any data type:
List new_list(int,int);
creates new list eg:
List list=new_list(TYPE_INT,sizeof(int));
//This will create an list of integers
Error append(List*,void*);
appends an element to the list. *Append accpts two pointers as an argument, if you want to store pointer to the list don't pass the pointer by pointer
eg:
//using the int list from above
int a=5;
Error err;
err=append(&list,&a)
//for an list of pointers
List listptr=new_list(TYPE_CUSTOM,sizeof(int*));
int num=7;
int *ptr=#
append(&listptr,ptr);
//for list of structs
struct Foo
{
int num;
float *ptr;
};
List list=new_list(TYPE_CUSTOM,sizeof(struct Foo));
struct Foo x;
x.num=9;
x.ptr=NULL;
append(&list,&x);
Error get(List*,int);
Gets data at index specified. When called list's current poiter will point to the data.
eg:
List list=new_list(TYPE_INT,sizeof(int));
int i;
for(i=1;i<=10;i++)
append(&list,&i);
//This will print the element at index 2
get(&list,2);
printf("%d",*(int*)list.current);
Error pop(List*,int);
Pops and element from the specified index
eg:
List list=new_list(TYPE_INT,sizeof(int));
int i;
for(i=1;i<=10;i++)
append(&list,&i);
//element in the index 2 will be deleted,
//the current pointer will point to a location that has a copy of the data
pop(&list,2);
printf("%d",*(int*)list.current);
//To use the list as stack, pop at index list.len-1
pop(&list,list.len-1);
//To use the list as queue, pop at index 0
pop(&list,0);
Error merge(List ,List);
Merges two list of same type. If types are different will return a error message in the Error object it returns;
eg:
//Merge two elements of type int
//List 2 will come after list 1
Error err;
err=merge(&list1,&list2);
Iterator get_iterator(List*);
Get an iterator to an list. when initialized will have a pointer to the first element of the list.
eg:
Iterator ite=get_iterator(&list);
Error next(Iterator*);
Get the next element of the list.
eg:
//How to iterate an list of integers
Iterator itr;
for(itr=get_iterator(&list); ite.content!=NULL; next(ite))
printf("%d",*(int*)ite.content);
https://github.com/malayh/C-List
i need in double linked list in C, but it must be for different types. In C++ we use templates for it. Where can i find example in C for double linked list with abstract types items.
Thank you
There are a few approaches you can take, one of which involves storing a void* in your ADT.
I've always found this to be a bit of a pain in a linked list since you have to manage it's allocation separately to the list itself. In other words, to allocate a node, you need to alocate both the node and its payload separately (and remember to clean them both up on deletion as well).
One approach I've used in the past is to have a 'variable sized' structure like:
typedef struct _tNode {
struct _tNode *prev;
struct _tNode *next;
char payload[1];
} tNode;
Now that doesn't look variable sized but let's allocate a structure thus:
typedef struct {
char Name[30];
char Addr[50];
char Phone[20];
} tPerson;
tNode *node = malloc (sizeof (tNode) - 1 + sizeof (tPerson));
Now you have a node that, for all intents and purposes, looks like this:
typedef struct _tNode {
struct _tNode *prev;
struct _tNode *next;
char Name[30];
char Addr[50];
char Phone[20];
} tNode;
or, in graphical form (where [n] means n bytes):
+------------+
| prev[4] |
+------------+
| next[4] |
+------------+ +-----------+
| payload[1] | | Name[30] | <- overlap
+------------+ +-----------+
| Addr[50] |
+-----------+
| Phone[20] |
+-----------+
That is, assuming you know how to address the payload correctly. This can be done as follows:
node->prev = NULL;
node->next = NULL;
tPerson *person = &(node->payload); // cast for easy changes to payload.
strcpy (person->Name, "Richard Cranium");
strcpy (person->Addr, "10 Smith St");
strcpy (person->Phone, "555-5555");
That cast line simply casts the address of the payload character (in the tNode type) to be an address of the actual tPerson payload type.
Using this method, you can carry any payload type you want in a node, even different payload types in each node, if you make the structure more like:
typedef struct _tNode {
struct _tNode *prev;
struct _tNode *next;
int payloadType; // Allows different payload type at each node.
char payload[1];
} tNode;
and use payloadType to store an indicator as to what the payload actually is.
This has the advantage over a union in that it doesn't waste space, as can be seen with the following:
union {
int fourBytes;
char oneHundredBytes[100];
} u;
where 96 bytes are wasted every time you store an integer type in the list (for a 4-byte integer).
The payload type in the tNode allows you to easily detect what type of payload this node is carrying, so your code can decide how to process it. You can use something along the lines of:
#define PAYLOAD_UNKNOWN 0
#define PAYLOAD_MANAGER 1
#define PAYLOAD_EMPLOYEE 2
#define PAYLOAD_CONTRACTOR 3
or (probably better):
typedef enum {
PAYLOAD_UNKNOWN,
PAYLOAD_MANAGER,
PAYLOAD_EMPLOYEE,
PAYLOAD_CONTRACTOR
} tPayLoad;
The only thing you need to watch out for is to ensure that the alignment of the payload is correct. Since both my payload placeholder and the payload are all char types, that's not an issue. However, if your payload consists of types with more stringent alignment requirements (such as something more strict than the pointers, you may need to adjust for it).
While I've never seen an environment with alignments more strict than pointers, it is possible according to the ISO C standard.
You can usually get the required alignment simply by using a data type for the payload placeholder which has the strictest alignment requirement such as:
long payload;
In retrospect, it occurs to me that you probably don't need an array as the payload placeholder. It's simple enough to just have something you can take the address of. I suspect that particular idiom of mine hearkens back to the days where I just stored an array of characters (rather than a structure) and referenced them directly. In that case, you could use payload[] on its own without casting to another type.
Handling arbitrary data in C is usually done by using pointers - specifically void * in most cases.
Obviously, the linux kernel uses linked lists in many, many places both in the kernel itself and in the many device driver modules. Almost all of these are implemented using the same a set of macros defined in linux/list.h
See http://isis.poly.edu/kulesh/stuff/src/klist/ or http://kernelnewbies.org/FAQ/LinkedLists for a good explanation.
The macros look a bit strange at first but are easy to use and soon become second nature. They can trivially be adapted for use in user space (see list.h).
The closest think in C to an "object" base class or templated types is a void pointer. A void * represents a pointer to something, but it does not specify what type of data is being pointed to. If you want to access the data, you need to use a cast.
A doubly linked list node could look like this:
struct DoubleLinkedListNode {
struct DoubleLinkedListNode *previous, *next;
void *data;
};
To assign a node a string, for example, you could do:
char myString[80] = "hello, world";
struct DoubleLinkedListNode myNode;
myNode.data = myString;
To get the string back from a node, you use a cast:
char *string = (char *)myNode.data;
puts(string);
To store a non-pointer, you need to make a pointer from the data. For structures, you may be able to simply dereference the instance if its lifetime is long enough (similar to the above example). If not, or if you're dealing with a primitive type (e.g. an int or float), you need to malloc some space. Just be sure to free the memory when you're done.
You could use macros as demonstrated here (this particular example implements generic hash-tables).