You need some way to mark AnotherStruct stData empty.
First check (or double-check) the documentation and comments related to
AnotherStruct, possibly ask those who made it if they are available, to find out if there is an official way to do what you want.Perhaps that struct has a pointer, and if it is null pointer, the struct is empty. Or perhaps there is an integer field where 0 or -1 or something can mean empty. Or even a boolean field to mark it empty.
If there aren't any of the above, perhaps you can add such a field, or such an interpretation of some field.
If above fails, add a boolean field to
MyDatato tell ifstDatais empty.You can also interpret some values (like, empty string? Full of 0xFF byte?) of
data1and/ordata2meaning emptystData.If you can't modify or reinterpret contents of either struct, then you could put empty and non-empty items in different containers (array, list, whatever you have). If
MyDataitems are allocated from heap one-by-one, then this is essentially same as having a free list.Variation of above, if you have empty and non-empty items all mixed up in one container, then you could have another container with pointers or indexes to the the non-empty items (or to the empty items, or whatever fits your need). This has the extra complication, that you need to keep two containers in sync, which may or may not be trivial.
You need some way to mark AnotherStruct stData empty.
First check (or double-check) the documentation and comments related to
AnotherStruct, possibly ask those who made it if they are available, to find out if there is an official way to do what you want.Perhaps that struct has a pointer, and if it is null pointer, the struct is empty. Or perhaps there is an integer field where 0 or -1 or something can mean empty. Or even a boolean field to mark it empty.
If there aren't any of the above, perhaps you can add such a field, or such an interpretation of some field.
If above fails, add a boolean field to
MyDatato tell ifstDatais empty.You can also interpret some values (like, empty string? Full of 0xFF byte?) of
data1and/ordata2meaning emptystData.If you can't modify or reinterpret contents of either struct, then you could put empty and non-empty items in different containers (array, list, whatever you have). If
MyDataitems are allocated from heap one-by-one, then this is essentially same as having a free list.Variation of above, if you have empty and non-empty items all mixed up in one container, then you could have another container with pointers or indexes to the the non-empty items (or to the empty items, or whatever fits your need). This has the extra complication, that you need to keep two containers in sync, which may or may not be trivial.
I find myself in a similar fix as you (did). I am required to packetize a given structure and knowing the exact number of bytes in the structure would help me serialize the structure. However, some structures are empty and hence, serialization fails to align exact number of bytes.
Although this is 3 years later, I found the following solution that worked for me:
Copytemplate <typename T> struct is_empty {
struct _checker: public T { uint8_t dummy; };
static bool const value = sizeof(_checker) == sizeof(T);
};
The result can be be queried as is_empty<T>::value and is available at compile time.
Copytemplate <typename S>
typedef union {
struct __attribute__((__packed__)) {
ObjId id;
S obj;
} dataStruct;
std::array<uint8_t, (sizeof(dataStruct) - is_empty<S>::value)> byteArray;
} _msg_t;
Here are the references:
- https://stackoverflow.com/a/4829036/1727678
- http://www.boost.org/doc/libs/1_63_0/libs/type_traits/doc/html/boost_typetraits/reference/is_empty.html
Hi! I started learning C a few months ago and I'm working on a simple application, it doesn't really matter.
What matters is that I'm not sure if I'm doing it alright. The application has an array of pointers to user structures, and I want this function to return a pointer to a structure that has the correct id.
I just wonder if it is required to check if the pointer isn't NULL for every pointer in the array, or is there a better way to do it?
And I know that it would be easier to read with typedefs (probably) but it's easier for me to understand what exactly I have to pass to the function :>
I also made sure for the function to return NULL if there is no user with the given id.
I tested this code and it works, I just don't know if there's a better way to do it, if it's readable or if my way of thinking is wrong/correct.
I just want to improve :3
enum UserRole {
REGULAR,
ADMIN,
MASTER
};
struct User {
enum UserRole role;
uint64_t id;
char* name;
char* surname;
};
struct User *get_user_by_id(struct User* users[MAX_USERS_AMOUNT], uint64_t id)
{
for (int i = 0; i < MAX_USERS_AMOUNT; i++) {
if (users[i] != NULL && users[i]->id == id) {
return users[i];
}
}
return NULL;
}Better option is to pass the user count to the function, so you don't need to iterate over the max length. Otherwise yes, you would need to check for null.
I would do that like this:
if (users[i] && users[i]->id == id) { ... }
using users[i] instead of users[i] != NULL because NULL is equal to 0 and any non-zero value is like true
You also need to check users because arrays are like pointers and they can be NULL so any use of the [] operator will result in an error.
How to check whether a struct's member is NULL in C? - Stack Overflow
c - Checking NULL for array of structures - Stack Overflow
struct pointer, check if null - C++ Forum
c - check whether structure is null - Stack Overflow
You probably meant
if (foo)
foo->value++;
Also your comment "obviously null pointer error" is not so obvious to me.
foo->value++; // obviously, null pointer error
Not so obvious to me why this is an error. value is an int, not an int *, so how can it ever be a NULL pointer?
I think you meant to perform the following check
A *foo = malloc(sizeof(A));
if( foo != NULL ) {
foo->value++; // increment value
} else {
// allocation failed, do something about it
}
When you malloc a structure enough memory is allocated to contain all members of that structure; you do not have allocate memory for every single member.
Note that the contents of the structure itself are uninitialized after the malloc call. To set the members to a deterministic state you can do any one of the following:
foo->value = 0;Similarly initialize all other membersmemset( foo, 0, sizeof(*foo) );This sets all bits within the structure to zerosA *foo = calloc( 1, sizeof(A) );callocautomatically zero initializes the allocated memory
ptr points to an array if you increment it, ptr start pointing to a memory out size array that is not null.
You can do something like:
ptr = arr;
while (ptr < (arr + sizeof(arr)/sizeof(arr[0])) ){
ptr++;
}
Note: this technique will nnot work for dynamic arrays.
To learn what is this formula about read: Weird behavior when printing array in C?
You can use ptr check for null if you traversing an array of pointers AND when you know that the end of such array is marked with NULL. You are not.
You actually are traversing an array of structures with the ptr pointing straight to the memory location of the first element.
You have to keep track of the size of the array (or amount of its filled elements) and just stop after you have gone through them all.
int count = 2;
struct student arr[count];
struct student* ptr = arr;
for (int i=0; i<count; i++) {
// do your stuff
ptr++; // place it in for if you like
}
In your code, the initialization
Outer_t outer_instance = {
{NULL},
{
0,
1,
2,
3,
table_defined_somewhere_else,
}
};
is invalid. You are trying to assign NULL to Outer_t.tableA which is of non-pointer type Inner_t. NULL can only be assigned to pointers.
Most C compilers define NULL as 0 or ((void*)0). Depending on your compiler, this syntax may be allowed but will be expanded to 0, effectively setting all fields in the first Inner_t structure to zero. In any case, this code will not do what I think you believe it will.
Your notion of tableA being undefined or non-existent is wrong. As your structures are currently defined, declaring an object of type Outer_t will automatically create two Inner_t objects as structure members (and those Inner_t structures will automatically create the objects they are composed of, etc). If outer_instance exists, then outer_instance.tableA and outer_instance.tableB are guaranteed to exist. They cannot be "undefined" (they are defined when you defined the Outer_t data type) or "NULL" (has no meaning except for pointers). A structure which has members defined is never "empty".
Now, it is a valid concern whether or not tableA or tableB have been initialized. There is no universally-appropriate way to do this. One method is to fill the entire structure with some pre-defined value when it is declared, and to check for the presence of that value as a sign that the structure has not been initialized. This assumes, however, that there is a value that you should never see as valid data within that structure; many times, such a value does not exist.
If you want to build your code in such a way that the members of Outer_t may or may not exist, then you should use pointers (such as Inner_t* tableA) as members of Outer_t instead of structures. That way, you can NULL the pointer to indicate a non-existent table. However, you would not be able to declare the contents of the inner structs at the same time as the outer struct in the manner which you currently do.
Edit:
Looking at your updated code, it appears that you are getting that particular error because you are trying to assign an object of type Items_t to a field of type Items_t*. Use &items_instance here and your error should go away (provided that items_instance is defined before outer_instance, and all elements of items_instance can be determined at compile time).
In the revised code, you're setting the first field of outer_instance to NULL, but trying to set the second field to items_instance directly. Since the field has type Items_t* but items_instance has type Items_t, you're getting a type error.
You want to set the field to the address of items_instance, so use &items_instance.
Just make sure you initialise the pointer to NULL:
text* t = NULL;
then later you can malloc on demand, e.g.:
if (t == NULL)
{
t = malloc(sizeof *t);
// NB: check for error here - malloc can fail!
}
t->head = foo;
Simply initialize the pointer whan it is defined
text* t = NULL;
In this case you can check whether an object that should be pointed to by the pointer was allocated
if ( t != NULL ) { /* some action */ }
or you can write
if ( t && t->head ) { /* some action */ }
Take into account that if a pointer is defined outside any function that is if it has the static storage duration then it initialized implicitly by the compiler to a null pointer constant.
Arrays in C cannot be "empty". They are never empty. If you declared an array of 10 elements you will always have an array of 10 elements. There's no way to say whether some element has been modified or not unless you yourself come up with some way to manually "mark" elements that you modify. For example, you can choose some reserved element value, which will designate an "empty" element.
In your case you declare an array of 10 pointers
node* array[10];
If you supply an initializer
node* array[10] = { 0 };
your array elements will have the initial value of null. You can use that value as a mark of an "empty" element.
node array[10]; //array of struct node type
//node *array[10]; //this becomes declaration of array of pointers
//assuming you have initialized all with 0.
for(i=0;i<10;i++)
if (array[i].data == 0)
//data modified.
//if you declare array of pointers check if(array[i]->data==0)
You may only compare a pointer to NULL. An Adjustment itself will never be NULL.
In C++, a "reference" denoted by & implies that the caller of your method is obligated to provide you with an object instance. There is no (NORMAL) way to call your method without an object. You are free to assume that you if your function is called, the aAdjustement will be set to something.
However, there are two gothas here:
(1) It will be set to something, but will that 'something' be meaningful? Is a Adjustement structure completely zeroed-out a valid value for your function? If not - then you may test that instead test nulliness. If any structure value combinations are invalid - use this as the discriminator. If all possible values are valid - then there's nothing to be checked.
(2) If you know the dark ways (tm), you actually CAN PASS a null-reference to this function. So your code is not "safe from nulls" just because "you used reference&". However, as I said, with use of & you clearly state that you disallow nulls. A caller that knows the dark ways(tm) may only blame himself when your function crashes.
disclaimer: "normal" and "the dark ways" are just buzzwords to hide extra complexity of a real professional explanation. If you play a bit with casting and */& operators, you will quickly discover how to get i.e. "int& boom" that would point to a zero-address. This is not so "dark" nor "magic", it's plain feature of the language and platform. However, (A) novice programmers and even somewhat experienced programmers tend to not know that references can be null, and (B) the convention of &-means-dont-pass-null is really well known and settled, so (A+B) please adapt to the convention and feel free to use it where adequate.