How to directly assign a struct into an array? - c

// Structure to store tuples of data
struct tuple {
double val;
int source; // 1 or 2, as in sample1 or sample2
};
// Assume both samples are of length n
double function(double* sample1, double* sample2, int n) {
struct tuple data[n*2];
for (int i = 0; i < n; i = i + 2) {
struct tuple t = {sample1[i], 1};
data[i] = t;
t = {sample2[i], 2};
data[i+1] = t;
// more processing
return value;
}
I want to avoid declaring struct tuple t inside the loop, since I shouldn't need to, but I can't figure out a way to declare and initialize a struct on the right hand side of an assignment. Is there a way this can be done?

If your sole intent is to avoid a named t variable, you can dispense with it for a pair of compound literals:
data[i] = (struct tuple){sample1[i], 1};
data[i + 1] = (struct tuple){sample2[i], 2};
It should satisfy any desire for terseness. Bear in mind you need to enable C11 (or C99) support for it to work. 1
1 - That variable length array kinda indicates you already do have it enabled.

Related

flexible array member in a nested struct

Is it valid C code to have flexible array members inside nested structs? So is my sample code below guarenteed to work as expected with a sane compiler?
#include <stdio.h>
#include <stdlib.h>
struct d {
char c;
int ns[];
};
struct c {
struct d d;
};
struct b {
struct c c;
};
struct a {
int n;
struct b b;
};
int main() {
const int n = 10;
struct a *pa = malloc(sizeof(*pa) + n * sizeof(pa->b.c.d.ns[0]));
pa->n = n;
pa->b.c.d.c = 1;
for (int i = 0; i < n; ++i) {
pa->b.c.d.ns[i] = i;
}
for (int i = 0; i < n; ++i) {
printf("%d\n", pa->b.c.d.ns[i] + pa->b.c.d.c);
}
free(pa);
}
It's not valid per the standard. I'm not sure how reliable it is in practice.
C11 (ISO/IEC 9899:2011), §6.7.2.1.3 says the following (emphasis mine):
A structure or union shall not contain a member with incomplete or function type (hence, a structure shall not contain an instance of itself, but may contain a pointer to an instance of itself), except that the last member of a structure with more than one named member may have incomplete array type; such a structure (and any union containing, possibly recursively, a member that is such a structure) shall not be a member of a structure or an element of an array.
Later on, §6.7.2.1.18 clarifies that the above is referring to flexible array members (FAMs):
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.
From some quick experimentation, GCC and Clang both add the trailing padding required to align the FAM properly even when the struct is nested, and only warn about structures with FAMs being members of other structures or arrays if -Wpedantic is passed, so take that as a sign that it'll probably work if you will :). It feels a bit hackish though.
Note that it probably wouldn't make sense to have the FAM anywhere but at the end. If you do
struct e {
struct d d;
int n;
} e;
, then e.d.ns[0] and e.n are likely to overlap in memory.
Try something like this;
struct d {
char c;
int ns[];
};
struct a {
int n;
int d_fam[];
};
int main() {
const int n = 10;
struct a *pa = malloc(offsetof (struct a, d_fam) + offsetof (stuct d, ns) + n * sizeof(int));
struct d *pd = pa + (uintptr_t) offsetof (struct a, d_fam);
pa->n = n;
pd->c = 1;
for (int i = 0; i < n; ++i) {
pd->ns[i] = i;
}
for (int i = 0; i < n; ++i) {
printf ("%d\n", pd->ns[i] + pd->c);
}
free(pa);
}

array initialization for one of the elements in the structure

I have initialized the array for one of the element in the structure, there were some errors in printing the output, please point the errors and guide in solving it . Thanks!
#include<stdio.h>
typedef struct person
{
int row[3];
int age;
}PERSON;
int main()
{
int i;
PERSON p;
PERSON *pptr=&p;
pptr->row[3] = {4,5,6};
for (i = 0; i < 3; i++) {
printf (" %d\n", pptr->row[i]);
}
return 0;
}
Array objects in C language are not assignable. You cannot set the values in the entire array by using assignment. So, to do what you are trying to do using assignment syntax is impossible.
You had a chance to initialize your array at the point of declaration, i.e. when you defined object p
PERSON p = { { 4, 5, 6 } };
but you did not use that chance. After that it is too late to do it using pure core language features.
To set the values in the entire array after the point of declaration you can use a library function, like memcpy, in combination with a compound literal
memcpy(pptr->row, (int []) {4, 5, 6}, sizeof pptr->row);
You can't assign values to array like this: pptr->row[3] = {4,5,6};. Such syntax is valid only at initialization. You need to set each value manually or initialize your array with the values you want, something like this: PERSON p = {{4,5,6}, 0};.
#include<stdio.h>
typedef struct person
{
int row[3];
int age;
}PERSON;
int main()
{
int i;
PERSON p;
PERSON *pptr=&p;
pptr->row[0] = 4;
pptr->row[1] = 5;
pptr->row[2] = 6;
for (i = 0; i < 3; i++) {
printf (" %d\n", pptr->row[i]);
}
return 0;
}
You can't initialize array like this pptr->row[3] = {4,5,6};, You can use the above method or use for loop to initialize array..
When you have done PERSON p;. object p is created containing indeterminate values.
It means all the data members are already initialized with garbage since it's on stack.
So, pptr->row[3] = {4,5,6}; is not the initialization of the array an not allowed in this case. The for loop method is the best in this case.
for (i = 0; i < 3; i++)
scanf("%d",&(pptr->row[i])); // prenthrsis is for human readability

How to set a constant value inside an array of structures?

typedef struct all{
int x;
int ast[5];
}ALL;
ALL x[5];
int main(void){
ALL y[5];
// ...
}
How will I be able to set a constant value to ast[5] so that all array variables will have the same value of ast[]?
typedef struct all {
int x;
int ast[5];
} ALL;
ALL x[5];
ALL constast = {0, {1, 2, 3, 4, 5}};
int main(void) {
ALL y[5] = {[0] = constast, [1] = constast, [2] = constast,
[3] = constast, [4] = constast};
// ...
}
I'm assuming from the tags that the question is for C and not C++.
You could have a function that takes the size of the struct array and returns a pointer to the start of the array, like this:
typedef struct my_struct{
int i;
int var[5];
} my_struct;
my_struct* init_my_struct(int size){
my_struct *ptr = malloc(size * sizeof(struct));
for(my_struct *i = ptr; (i - ptr) < size; i++)
i->var = // whatever value you want to assign to it
// or copy a static value to the the array element
}
Now you can use it in your code in this way:
my_struct *my_struct_ptr = init_my_struct(5); // values inited as required
The drawbacks of this approach are that you are moving from declaring an array to using memory on the heap.
Also, you cannot keep someone from creating an array of a certain size and using it with values being assigned to it the way you would want.

Adding (or doing any other math) every member of two same structs with less code

So, basically, I want to addify every member of first struct, with every member of second struct, and the structs are of same type. Like this:
struct Foo
{
int bar1;
int bar2;
int bar3;
int bar4;
int bar5;
}
Foo AddFoos(Foo foo1, Foo foo2)
{
Foo foo3;
foo3.bar1 = foo1.bar1 + foo2.bar1;
foo3.bar2 = foo1.bar2 + foo2.bar2;
foo3.bar3 = foo1.bar3 + foo2.bar3;
foo3.bar4 = foo1.bar4 + foo2.bar4;
foo3.bar5 = foo1.bar5 + foo2.bar5;
return foo3;
}
However, when structs keep getting bigger, this way is weird. Is there any way to do it with less lines of code? And preferably without advanced pointer magic?
Use an array instead and a for loop to add the numbers:
struct Foo
{
int bars[100];
};
for (i=0;i<100;i++)
{
foo3.bars[i]=foo1.bars[i]+foo2.bars[i];
}
You can malloc if the array size is unknown at compile time and change the struct to this and then malloc for all three Foo variables.
struct Foo
{
int *bars;
};
You want the comfort of named fields (bar1 .. barN) and something like an array you can loop over to automate the operations. First we define the struct (a dense representation of the fields in memory):
struct VectorFields {
int a;
int b;
int c;
};
Then we need to get to know the number of the fields used in that struct:
#define VECTOR_FIELDS_LEN (sizeof(struct VectorFields) / sizeof(int))
(In C++ you could use some template magic foo, here we just use the preprocessor as a simpler variant). Next, we combine the struct VectorFields with an array of int so both match in size, also known as union:
union Vector {
struct VectorFields fields;
int raw[VECTOR_FIELD_LEN];
};
(Note: VECTOR_FIELD_LEN must be a known constant value to the compiler, hence the preprocessor thingy before.) You are now able to access the data either by it's name (.fields.a) or by an index (.raw[0]). So, let's write the function which adds the Vector together:
void vector_add(union Vector* result, union Vector* a, union Vector* b) {
int i;
for (i = 0; i < TUPLE_LEN; i++) {
result->raw[i] = a->raw[i] + b->raw[i];
}
}
You might use it like this then:
#include <stdio.h>
int main() {
union Vector a = { .fields = { 1, 2, 3 } };
union Vector b = { .fields = { 4, 5, 6 } };
union Vector sum;
vector_add(&sum, &a, &b);
printf("%d %d %d\n", sum.fields.a, sum.fields.b, sum.fields.c);
return 0;
}
Depending on what you call "advanced pointer magic", you can use the following moderately magical code:
Foo AddFoos(Foo foo1, Foo foo2)
{
Foo foo3;
int *pointer1 = &foo1.bar1; // first field here
int *pointer2 = &foo2.bar1; // first field here
int *pointer3 = &foo3.bar1; // first field here
while (pointer3 <= &foo3.bar5) // last field here
{
*pointer3++ = *pointer1++ + *pointer2++;
}
return foo3;
}
When you change the definition of Foo, just update the names of the first and last field.
This will only work when all fields are of the same type.
If you have only ints you can use an array
struct Foo {
int bar[5];
};
Foo AddFoos(Foo f1, Foo f2)
{
Foo f3;
int i;
for (i = 0; i < 5; ++i)
f3.bar[i] = f1.bar[i] + f2.bar[i];
return f3;
}

C array sorting using qsort?

I have been stuck on this for a while and nothing seems to work.
I have a data structure:
DATA
{
int size;
int id;
}
And I have an array of DATA structures:
myArray = (DATA *) malloc(10 * sizeof(DATA));
Then I assign some test values:
myArray[0].size = 5;
myArray[1].size = 9;
myArray[2].size = 1;
myArray[3].size = 3;
So my starting array should look like:
5,9,1,3,0,0,0,0,0,0
Then, I call qsort(myArray,10,sizeof(DATA),comp)
Where comp is:
int comp(const DATA * a, const DATA * b)
{
return a.size - b.size;
}
And trust me, I tried many things with the compare function, NOTHING seems to work. I just never get any sorting that makes any sense.
So my starting array should look like 5, 9, 1, 3, 0, 0, 0, 0, 0, 0.
No, it really won't, at least it's not guaranteed to.
If you want zeros in there, either use calloc() to zero everything out, or put them in yourself. What malloc() will give you is a block of the size required that has indeterminant content. In other words, it may well have whatever rubbish was in memory beforehand.
And, on top of that, a and b are pointers in your comp function, you should be using -> rather than . and it's good form to use the correct prototype with casting.
And a final note: please don't cast the return from malloc in C - you can get into problems if you accidentally forget to include the relevant header file and your integers aren't compatible with your pointers.
The malloc function returns a void * which will quite happily convert implicitly into any other pointer.
Here's a complete program with those fixes:
#include <stdio.h>
#include <stdlib.h>
typedef struct {int size; int id;} DATA;
int comp (const void *a, const void *b) {
return ((DATA *)a)->size - ((DATA *)b)->size;
}
int main (void) {
int i;
DATA *myArray = malloc(10 * sizeof(DATA));
myArray[0].size = 5;
myArray[1].size = 9;
myArray[2].size = 1;
myArray[3].size = 3;
for (i = 4; i < 10; i++)
myArray[i].size = 0;
qsort (myArray, 10, sizeof(DATA), comp);
for (i = 0; i < 10; i++)
printf ("%d ", myArray[i].size);
putchar ('\n');
return 0;
}
The output:
0 0 0 0 0 0 1 3 5 9

Resources