For example I have a struct
struct s{
char c;
int x;
};
And I use calloc() to allocate memory.
s *sp = (s*) calloc(1, sizeof(s));
Now, what will be the values of sp->c and sp->x?
"What will be the values of sp->c and sp->x?"
Since calloc() sets all bits of the allocated memory to 0, c and x will have the value of 0 if the 0 value representation of int and char is of all bits to 0 (which is common).
Note that in the case of pointers, the pointer might not be standard-compliant NULL pointer when just setting all bits to 0 as the C standard does not require the representation of NULL pointers to be all-zero-bits.
Side notes:
1.
struct s{
char c;
int x;
};
s *sp = (s*) calloc(1, sizeof(s));
can´t work as s isn´t a typedefd type; it is a structure tag. Therefore, You need to precede s by the struct keyword:
struct s *sp = (struct s*) calloc(1, sizeof(struct s));
2.
You do not need to cast the returned pointer from calloc() and other memory management functions and rather avoid it since it can add clutter to your code. -> Do I cast the result of malloc
So, just do:
struct s *sp = calloc(1, sizeof(struct s));
Related
#define DEFAULT_SIZE 100
struct my_struct {
struct some_struct *ptr;
size_t len;
char buf[0];
};
struct my_struct *s;
s = malloc(sizeof *s + DEFAULT_SIZE);
...
Now, assuming I want to expand the buf memory. Do I need to re-create struct my_struct * with realloc() call? Can't I simply reallocate memory occupied by buf, i.e. :
realloc(s->buf, 2* DEFAULT_SIZE);
No. You can only realloc a pointer returned by malloc. malloc gave you the pointer to the entire structure, so that is what you may realloc.
I've been trying to implement a generic array searcher and came across this answer, which made me think that my implementation is only valid for dynamically allocated arrays.
The implementation looks like this:
void *array_search( void *arr,
size_t elem_size,
size_t len,
arr_search_checker v,
void *match)
{
char *p = arr;
for(unsigned i = 0; i < len; ++i)
{
if(v((void *) p, match))
return p;
p += elem_size;
}
return NULL;
}
The type arr_search_checker:
typedef bool (*arr_search_checker)(void *, void *);
Having a simple structure:
struct test_struct { int i; char c; };
And a check function:
bool test_checker(void *l, void *r)
{
struct test_struct *ls = l, *rs = r;
return ls->i == rs->i && ls->c == rs->c;
}
And array of length len which is an array of struct test_struct one can invoke the searcher:
struct test_struct match = { .i = 5, .c = 'A' };
struct test_struct *res = array_search(array,
sizeof(struct test_struct), len, test_checker, &match);
Is that true that this implementation of array_search is only valid for dynamically allocated arrays because of incrementation of the char pointer p by size of the single element in the array what can be dangerous for padded arrays? Or is it totally invalid?
Please state your question in the question topic.
The function array_search as valid for any arrays (don't know why dynamically allocated arrays are particular in any way). Char pointer p is incremented by elem_size. elem_size is assigned the value of sizeof(struct test_struct) in your example and that's perfectly ok. Padding has nothing to do with it. Imagine struct test_struct has some padding bytes added to it (anywhere, at the end of the structure or between any of it members). Then sizeof(struct test_struct) will be the size of the test_struct structure including the padding bytes, and p will still be increment correctly.
You may convert any pointer to void* and any pointer to char* without braking the strict aliasing rule. You cannot do arithmetic on void* pointers, that's why it gets converted to char* pointer. elem_size represents the size of a single array element in bytes, char represents one byte in memory, by doing p += elem_size; you add elem_size bytes to p (I like the form p = &p[elem_size];). The smallest addressable size in C is one byte (remember that byte may not be 8 bits) and the size of every structure or type in C must be an integral value (ie. sizeof(struct test_struct) cannot return 1,5).
For more, look at bsearch and qsort functions from standard C library. They have a very similar declaration to array_search and work with any array types, just like array_search here.
I'm currently learning C and I have trouble understanding the following code:
struct dns_header
{
unsigned char ra : 1;
unsigned char z : 1;
unsigned char ad : 1;
unsigned char cd : 1;
unsigned char rcode : 4;
unsigned short q_count : 16;
};
int main(void)
{
struct dns_header *ptr;
unsigned char buffer[256];
ptr = (struct dns_header *) &buffer;
ptr->ra = 0;
ptr->z = 0;
ptr->ad = 0;
ptr->cd = 0;
ptr->rcode = 0;
ptr->q_count = htons(1);
}
The line I don't understand is ptr = (struct dns_header *) &buffer;
Can anyone explain this in detail?
Your buffer is simply a contiguous array of raw bytes. They have no semantic from the buffer point of view: you cannot do something like buffer->ra = 1.
However, from a struct dns_header * point of view those bytes would become meaningful. What you are doing with ptr = (struct dns_header *) &buffer; is mapping your pointer to your data.
ptr will now points on the beginning of your array of data. It means that when you write a value (ptr->ra = 0), you are actually modifying byte 0 from buffer.
You are casting the view of a struct dns_header pointer of your buffer array.
The buffer is just serving as an area of memory -- that it's an array of characters is unimportant to this code; it could be an array of any other type, as long as it were the correct size.
The struct defines how you're using that memory -- as a bitfield, it presents that with extreme specificity.
That said, presumably you're sending this structure out over the network -- the code that does the network IO probably expects to be passed a buffer that's in the form of a character array, because that's intrinsically the sanest option -- network IO being done in terms of sending bytes.
Suppose you want to allocate space for the struct so you could
ptr = malloc(sizeof(struct dns_header));
which will return a pointer to the allocated memory,
ptr = (struct dns_header *) &buffer;
is almost the same, except that in this case it's allocated in the stack, and it's not necessary to take the address of the array, it can be
ptr = (struct dns_header *) &buffer[0];
or just
ptr = (struct dns_header *) buffer;
there is no problem in that though, because the addresses will be the same.
The line I don't understand is ptr = (struct dns_header *) &buffer;
You take the address of the array and pretend like it is a pointer to a dns_header. It is basically raw memory access, which is unsafe, but OK if you know what you are doing. Doing so will grant you access to write a dns_header in the beginning of the array.
Ideally, it should be an array of dns_headers not a byte array. You have to be cautious about the fact that dns_header contains bit fields, the implementation of which is not enforced by the standard, it is entirely up to the compiler vendors. Although bit field implementations are fairly "sane", there is no guarantee, so the size of a byte array might actually be mismatched with your intent.
Adding to the other answers posted:
This code is illegal since ANSI C. ptr->q_count = htons(1); violates the strict aliasing rule.
It is only permitted to use an unsigned short lvalue (i.e. the expression ptr->q_count) to access memory that either has no declared type (e.g. malloc'd space), or has declared type of short or unsigned short or compatible.
To use this code as-is, you should pass -fno-strict-aliasing to gcc or clang. Other compilers may or may not have a similar flag.
An improved version of the same code (which also has some forwards-compatibility to the structure size changing) is:
struct dns_header d = { 0 };
d.q_count = htons(1);
unsigned char *buffer = (unsigned char *)&d;
This is legal because the strict aliasing rule permits unsigned char to alias anything.
Note that buffer is currently unused in this code. If your code is actually a smaller snippet of larger code then buffer may have to be defined differently. In any case, it could be in a union with d.
A struct directly references a contiguous block of memory and each field within a struct is located at a certain fixed offset from the start. Variables can then be accessed via a struct pointer or by the struct declared name which returns the same address.
Here we declare a packed struct which references a contiguous block of memory:
#pragma pack(push, 1)
struct my_struct
{
unsigned char b0;
unsigned char b1;
unsigned char b2;
unsigned char b3;
unsigned char b4;
};
#pragma pack(pop)
Pointers can then be used to refer to the struct by its address. See this example:
int main(void)
{
struct my_struct *ptr;
unsigned char buffer[5];
ptr = (struct my_struct *) buffer;
ptr->b0 = 'h';
ptr->b1 = 'e';
ptr->b2 = 'l';
ptr->b3 = 'l';
ptr->b4 = 'o';
for (int i = 0; i < 5; i++)
{
putchar(buffer[i]); // Print "hello"
}
return 0;
}
Here we explicitly map 1:1 the struct contiguous block of memory to the contiguous block of memory pointed by buffer (using the address to the first element).
An array address and the name of the address are numerically identical but have different types. These two lines are thus equivalent:
ptr = (struct my_struct *) buffer;
ptr = (struct my_struct *) &buffer;
This is usually not a problem if we use the address as is and cast it appropriately. Dereferencing an array address of type pointer to array-of-type yields the same pointer but with a different type array-of-type.
Although it might seem convenient to manipulate memory in this fashion, it is strongly discouraged as the resulting code becomes painfully difficult to understand. If you really have no choice, I suggest using an union to specify that the struct is to be used in a particular manner.
I'm trying to use memset on a struct element like so:
memset( &targs[i]->cs, 0, sizeof( xcpu ) );
However, doing so gives me a segmentation fault. I neither understand why this is failing, nor how I can make it work. What is the proper way to use memset on an element of a struct, and why does my method not work?
Line which allocates memory for targs:
eargs **targs = (eargs **) malloc(p * sizeof(eargs *));
Struct definitions for struct element cs (xcpu_context) and struct targs (execute_args):
typedef struct xcpu_context {
unsigned char *memory;
unsigned short regs[X_MAX_REGS];
unsigned short pc;
unsigned short state;
unsigned short itr;
unsigned short id;
unsigned short num;
} xcpu;
typedef struct execute_args {
int ticks;
int quantum;
xcpu cs;
} eargs;
You have allocated an array of pointers in the line
eargs **targs = (eargs **) malloc(p * sizeof(eargs *));
but you haven't initialized the elements themselves. So this segfault has nothing to do with properly using memset on the fields of a struct, but instead derives from using uininitialized memory (assuming that you don't have a loop to initialize each eargs object after you allocate the array of pointers).
Instead, if you wanted to allocate a dynamic array of p eargs objects (I'm using the term "objects" loosely here), you would write
eargs *args = malloc(p * sizeof(eargs));
if (!args) {
/* Exit with an error message */
}
memset(&(args[i].cs), 0, sizeof(xcpu));
instead. Note that args is a dynamically allocated array of eargs objects, not a dynamically allocated array of pointers, so it's of type eargs * rather than eargs **.
Your memory allocation line doesn't allocate any memory for any structures, only for pointers to structures. If you want to allocate memory for that whole array, you need to add a loop to allocate memory for the structures themselves:
for (i = 0; i < p; i++)
targs[i] = malloc(sizeof(eargs));
Once you actually have structures to operate on, your memset() call should be fine.
For some reason if I try to get the actual size of mystruct I keep getting size 1.
I know that mystruct is holding the data cause I can dump it out and everything is in mystruct.
What could be the reason of getting size 1?
Thanks
// fragments of my code
struct mystruct {
char *raw;
int count;
};
struct counter {
int total; // = 30
}
static struct mystruct **proc()
{
int i = 0;
gchar *key,*val;
struct mystruct **a_struct;
struct counter c;
a_struct = (struct mystruct **)malloc(sizeof(struct mystruct *)*c.total);
while (table (&iter, (gpointer) &key, (gpointer) &val)) {
a_struct[i] = (struct mystruct *)malloc(sizeof(struct mystruct));
a_struct[i]->raw = (char*)key;
a_struct[i++]->count = (int)val;
}
size_t l = sizeof(a_struct) / sizeof(struct mystruct*);
printf("%d",l); // outputs 1
}
You're doing a couple things wrong. First, you're taking sizeof(a_struct) which is going to be the size of a pointer (since that's what a_struct is) and then dividing by the size of another pointer. Guaranteed 1.
Besides that, why are you doing a division at all? What I think you want is:
size_t l = sizeof(struct mystruct);
or
size_t l = sizeof(**a_struct);
Edit:
I think I see the reason for your division now; you're trying to find the size of that array. That's not going to work - sizeof can only work at compile time in C (with some special exceptions in C99 which don't apply to your code), so it can't figure out the size of a dynamic array like that.
you're dividing the size of a pointer by the size of a pointer.
a_struct is a double pointer to struct mystruct.
struct mystruct * is a pointer to struct mystruct.
Both there sizes will be same.
Do this size_t l = sizeof(struct mystruct);
You are taking the size of two pointers and dividing one by the other,
size_t l = sizeof(a_struct) / sizeof(struct mystruct*);
a_struct is declared as struct mystruct **a_struct so this is the same as saying
size_t l = sizeof(struct mystruct **) / sizeof(struct mystruct*);
since all pointers have the same size, ** is the same size as *, so this will always evaluate to 1.
I'm not quite sure what you are trying to print out here, the size of a_struct ? or the total allocation size? The size of a_struct is just c.total, the total allocation is the sum of all of the values that you passed to malloc.