Why the content is not printed well (e.g. Segmentation Fault/NULL)? I'm passing the entire nested struct (i.e. the array list lp) to the main list. Any suggestion? I spent two days to understand what I wrong without success. I would to have an explanation about it.
#include <stdio.h>
#include <string.h>
struct list
{
char *a;
char *b;
} lp[10];
typedef struct
{
int k;
struct list thelist[2];
} palist;
int main()
{
lp[0].a = "One";
lp[0].b = "Two";
lp[1].a = "Three";
lp[1].b = "Four";
palist final_list = {10, *lp};
printf("%s, %s", final_list.thelist[1].a, final_list.thelist[1].b);
return 0;
}
What you have to understand is that on access, an array is converted to a pointer to the first element (subject to 4-exceptions not relevant here) C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3)
When you attempt to initialize thelist with *lp you are attempting to initialize an array of struct list from the first element in lp. Assuming you change the intialization from {10, *lp} to (10, lp) that still will not work because now lp is a pointer to the first element which you attempt to use to initialize an array.
In order to accommodate the array/pointer conversion, you need to declare thelist as a pointer not an array, e.g.
typedef struct
{
int k;
struct list *thelist;
} palist;
(You can initialize a pointer with a pointer and all will be well)
Now using the initializer {10, lp} will provide a pointer for the initialization of thelist and your assignment will work (but you must keep track of the number of elements that are valid -- final_list[2].... would invoke Undefined Behavior as the elements 2 and beyond are not initialized)
Your total code would be:
#include <stdio.h>
struct list
{
char *a;
char *b;
} lp[10];
typedef struct
{
int k;
struct list *thelist;
} palist;
int main(void) {
lp[0].a = "One";
lp[0].b = "Two";
lp[1].a = "Three";
lp[1].b = "Four";
palist final_list = {10, lp};
printf("%s, %s\n", final_list.thelist[1].a, final_list.thelist[1].b);
return 0;
}
There are many other ways to initialize or assign this list in the form with the array
typedef struct
{
int k;
struct list thelist[2];
} palist;
for example
palist final_list = {10, {lp[0], lp[1]}};
final_list = (palist){10, {lp[0], lp[1]}};
final_list = (palist){10,};
memcpy(final_list.thelist, lp, sizeof(final_list.thelist));
https://godbolt.org/z/fUjLtE
Related
In my project, I am asked to store my 2D array of words in a dynamic data structure, then use them in other functions for other purposes, but I am confused how should I do this. I do understand, how to name them separately like:
#include <stdio.h>
#include <stdlib.h>
typedef struct Names {
char *name[5];
} Names;
void func(Names y) {
printf("%s\n%s", y.name[0], y.name[1]);
}
int main()
{
Names y;
y.name[0] = "John";
y.name[1] = "Luke";
func(y);
return 0;
}
But what if I wanted to do this as a 2d array. So normally I would do char names[][10] = {"John", "Luke", etc..}; but how do I store that in a struct? I mean if I did
#include <stdio.h>
#include <stdlib.h>
typedef struct Names {
char *name[5][10];
} Names;
void func(Names y) {
printf("%s\n%s", y.name[0], y.name[1]);
}
int main()
{
Names y;
y.name[][10] = {"John", "Luke"};
func(y);
return 0;
}
That would just give errors and make no sense.
This is the official way to do it (see Nested initialization in: Struct and union initialization):
#include <stdio.h>
typedef struct Names {
const char *name[2][2];
} Names;
void func(Names* y) {
printf("%s, %s\n", y->name[0][0], y->name[0][1]);
printf("%s, %s\n", y->name[1][0], y->name[1][1]);
}
int main()
{
Names y = { .name={{"John", "Luke"}, {"Jack", "Jim"}}};
func(&y);
return 0;
}
Also the following works for backwords-compatibility reasons:
#include <stdio.h>
typedef struct Names {
const char *name[2][2];
} Names;
void func(Names* y) {
printf("%s, %s\n", y->name[0][0], y->name[0][1]);
printf("%s, %s\n", y->name[1][0], y->name[1][1]);
}
int main()
{
Names y = {"John", "Luke", "Jack", "Jim"};
func(&y);
return 0;
}
The above is managing string constants stored in const char pointers, for variable strings of up to 9 chars lentgh with a trailing zero-terminator, something like the following will be possible (I made compile-time constants for 5 and 9):
#include <stdio.h>
enum {
NAME_COUNT = 5,
NAME_LENGTH = 9
};
typedef struct Names {
char name[NAME_COUNT][NAME_LENGTH+1];
} Names;
void func(Names* y) {
for (int i=0; i<NAME_COUNT; ++i) {
printf("%s\n", y->name[i]);
}
}
int main()
{
Names y = { .name={"John", "Olivia", "Luke", "Mary", "Jane" }};
func(&y);
return 0;
}
I think what you may be missing is the fact that char *name[5]; is not really a 2d array of words, it's an array of 5 pointers to char, you then make the two first pointers of that array point to two string literals. In the second expression you have a 5 by 10 2d array of pointers to char, each one of these pointer can also point to its own string literal, so naturally the expression:
y.name[][10] = {"John", "Luke"};
Is not correct for several reasons, the compiler needs to know both dimensions of the array to know to which pointer you want to assign the string literal, knowing this you'll note that the assigned expression makes little sense.
Example:
y.name[1][1] = "John";
Here you would assign the string literal "John" to the pointer located in the index [1][1] of the array of pointers.
Now, if you want an array of 5 words each one containing 10 characters, including the null byte you would simply use:
char name [5][10]
Note that in this configuration you can't simply assign the strings, you'll need to copy them using somenthing like strcpy.
strcpy(y.name[0], "John");
I have created below C struct.
typedef struct KnightsMartSale {
char firstName[21];
char lastName[21];
int numItemsOnList;
int *itemsPurchased; // array of item numbers
struct KnightsMartSale *next;
} KMSale;
Here is it possible to assign int array to the int *itemsPurchased pointer?
If it is possible how print the values?
I'd allocate memory according to the size of the array you want to copy into itemsPurchased and also "remember" the number of possible items in numItemsOnList.
So suppose you have a given array of ints, let's say myArray, then the code for copying and printing could look as follows:
typedef struct KnightsMartSale {
char firstName[21];
char lastName[21];
int numItemsOnList;
int *itemsPurchased; // array of item numbers
struct KnightsMartSale *next;
} KMSale;
int main() {
KMSale kmsale;
int myArray[] = { 20,30,40,50 };
kmsale.numItemsOnList = sizeof(myArray)/sizeof(myArray[0]);
kmsale.itemsPurchased = calloc(kmsale.numItemsOnList,sizeof(int));
memcpy(kmsale.itemsPurchased,myArray,kmsale.numItemsOnList*sizeof(int));
for (int i=0; i<kmsale.numItemsOnList; i++) {
printf("item #%d: %d\n",i,kmsale.itemsPurchased[i]);
}
// kmsale not needed any more, free memory:
free(kmsale.itemsPurchased);
}
Output:
item #0: 20
item #1: 30
item #2: 40
item #3: 50
Just some rapid prototype coding... Perhaps it might direct you into the right way...
KMSale foo; // sample struct on stack, not initialized!
int my_buffer[12]; // not initialized stack buffer!
/* Assign pointer */
foo.itemsPurchased = my_buffer; // point to my_buffer
/* Print the first element via the struct... */
printf("%02x", foo.itemsPurchased[0]);
Here is it possible to assign int array to the int *itemsPurchased pointer? If it is possible how print the values?
Yes we can assign an array to a pointer as array is a constant pointer and reverse is invalid.
But this assignment should be used very carefully as array will be a stack variable and scope of the variable should be taken care before accessing this structure pointer
Also this method can be preferred over the dynamic memory allocation where memory fragmentation is a concern by malloc and free and we can avoid the dynamic allocation overhead.
Following is the code for this and output of print value in the array:
#include <stdio.h>
typedef struct KnightsMartSale {
char firstName[21];
char lastName[21];
int numItemsOnList;
int *itemsPurchased; // array of item numbers
struct KnightsMartSale *next;
} KMSale;
int main() {
KMSale sale;
int iPos = 0;
int Array[] = {1, 2, 3, 4, 5};
sale.numItemsOnList = sizeof(Array) / sizeof(Array[0]);
sale.itemsPurchased = Array;
for (iPos=0; iPos < sale.numItemsOnList; iPos++) {
printf("sale %d: %d\n", iPos, sale.itemsPurchased[iPos]);
}
return 0;
}
output:
sale 0: 1
sale 1: 2
sale 2: 3
sale 3: 4
sale 4: 5
I have a function test that accepts a pointer to a structure. How can I set the value of a field in a structure in the nested structure array? The structures are created and deleted elsewhere, I just want to set the value.
typedef struct {
int a;
} inner_struct_t;
typedef struct {
int b;
inner_struct_t innerStructsArr[];
} outer_struct_t;
void test(outer_struct_t *outerStruct);
void test(outer_struct_t *outerStruct) {
outerStruct->b = 123; // set a value in the outer struct
(outerStruct->innerStructsArr)[0].a = 456; // but this DOESN'T work
}
Here's a complete example that should work for you:
#include <stdio.h>
#include <malloc.h>
typedef struct {
int a;
} inner_struct_t;
typedef struct {
int b;
inner_struct_t *innerStructsArr;
} outer_struct_t;
void test(outer_struct_t *outerStruct, int n) {
outerStruct->b = 123; // set a value in the outer struct
outerStruct->innerStructsArr = malloc(sizeof(inner_struct_t) * n); // Allocate space
outerStruct->innerStructsArr[0].a = 456; // Assign a value
}
int main (int argc, char *argv[]) {
outer_struct_t s;
test(&s, 1);
printf("b=%d, inner[0]=%d\n", s.b, s.innerStructsArr[0].a);
free(s.innerStructsArr);
return 0;
}
When you have a structure with a flexible array member (FAM) in it, you need to allocate the space for the array at the same time that you allocate the space for the structure.
ISO/IEC 9899:2011 §6.7.2.1 Structure and union specifiers
¶18 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. In most situations,
the flexible array member is ignored. In particular, the size of the structure is as if the
flexible array member were omitted except that it may have more trailing padding than
the omission would imply. However, when a . (or ->) operator has a left operand that is
(a pointer to) a structure with a flexible array member and the right operand names that
member, it behaves as if that member were replaced with the longest array (with the same
element type) that would not make the structure larger than the object being accessed; the
offset of the array shall remain that of the flexible array member, even if this would differ
from that of the replacement array. If this array would have no elements, it behaves as if
it had one element but the behavior is undefined if any attempt is made to access that
element or to generate a pointer one past it.
Given:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int a;
} inner_struct_t;
typedef struct
{
int b;
inner_struct_t innerStructsArr[];
} outer_struct_t;
static void test(outer_struct_t *outerStruct)
{
outerStruct->b = 123;
outerStruct->innerStructsArr[0].a = 456;
}
int main(void)
{
outer_struct_t *os = malloc(sizeof(*os) + 4 * sizeof(os->innerStructsArr[0]));
for (int i = 0; i < 4; i++)
os->innerStructsArr[i].a = 10 * i;
test(os);
printf(" b = %d\n", os->b);
for (int i = 0; i < 4; i++)
printf("[%d].a = %d\n", i, os->innerStructsArr[i].a);
free(os);
return 0;
}
Sample output:
b = 123
[0].a = 456
[1].a = 10
[2].a = 20
[3].a = 30
So I made a struct with a with an uninitialized array inside but the outer struct is an array that is initialized. I then loop through and print the values but I'm not getting anything. NUM is already defined as 12.
#include "header.h"
#include <stdio.h>
#include <stdlib.h>
void make() {
struct suit {
char *type;
int people[];
} deck[4] = {"Hunter", NUM,
"Fighter", NUM,
"Jumper", NUM,
"Strider", NUM};
};
//print type and numbers 1-12
for (int i = 0; i < 4; i++) {
for (int j = 0; j < NUM; i++) {
printf(deck[i].type);
printf(deck[i].people[j]);
}
}
}
Allocate the memory of int people[]; array, So, your struct should look like this, since it is an object definition:
struct suit {
char *type;
int people[10]; //compile time allocation
} deck[4] = {"Hunter", NUM,
"Fighter", NUM,
"Jumper", NUM,
"Strider", NUM};
people is a flexible array member and Standard C does not allow initialization of flexible array member. Though, GCC allows static initialization of flexible array as an extension. So,
struct suit {
char *type;
int people[];
} deck = {"Hunter", NUM};
is valid snippet as per GCC, but at the same time GCC doesn't allow nested array initialization when flexible array member is involved and therefore the initializer for deck[4] is not valid.
Of course, this extension only makes sense if the extra data comes at the end of a top-level object, as otherwise we would be overwriting data at subsequent offsets. To avoid undue complication and confusion with initialization of deeply nested arrays, we simply disallow any non-empty initialization except when the structure is the top-level object. For example:
struct foo { int x; int y[]; };
struct bar { struct foo z; };
struct foo a = { 1, { 2, 3, 4 } }; // Valid.
struct bar b = { { 1, { 2, 3, 4 } } }; // Invalid.
struct bar c = { { 1, { } } }; // Valid.
struct foo d[1] = { { 1, { 2, 3, 4 } } }; // Invalid.
Also note that you should use appropriate format specifiers in printf for different data types.
I have a structure as follows
struct a
{
char* ap;
char* inputs[10];
int e;
};
then I have created an array of this structure like struct a list [100];
now i want to fille the array inputs[10] and for that I am using the syntax to access the first location :
ip=0;
inp=0;
list[ip].inputs[inp]
but I am gettin the error "error C2107: illegal index, indirection not allowed" on compiling the code
please suggest how to access the array location inside array of structure.
regards
priya
Here you use array of character pointer in your structure. So Initially you allocate memory for you structure by creation list of 100. I think you didn't create memory for you array of character pointer. You have to create memory for each of character pointer. So I suggest example code.
#include <stdio.h>
struct a
{
char* ap;
char* inputs[10];
int e;
};
int main()
{
int ip=0;
int inp=0;
struct a list[100];
list[ip].inputs[inp]= (char*)malloc(25);
scanf("%s",list[ip].inputs[inp]);//Or other copy function to fill string
printf("output %s",list[ip].inputs[inp]);
}
Working fine on my pc.. here is my code..
#include <stdio.h>
struct a
{
char* ap;
char* inputs[10];
int e;
};
int main()
{
int ip=0;
int inp=0;
struct a list[100];
list[ip].inputs[inp] = 'A';
printf("This: %c", list[ip].inputs[ip]);
return 0;
}
OUTPUT= This: A
let me know whether it helped or not..
The struct themselves do not have data. You need to create objects of the struct type and set the objects ...
struct a
{
char* ap;
char* inputs[10];
int e;
};
/* I like to separate the type definition from the object creation */
struct a list [3];
list [0].inputs[0] = "Choclate";
list [0].inputs[1] = "Almond";
list [0].inputs[2] = "Rasberry";
Hope it ll usefull. Also refer this article