2

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;
}
CipherX
  • 371
  • 5
  • 18
  • 1
    `lp` is an array of structs, why are you using `*lp`, try using just `lp` – kiner_shah Jun 14 '20 at 08:09
  • 1
    in `palist`, `thelist` is an **array**. You attempt to initialize with `*lp` which is simply the first `struct list` in `lp`. That won't work. – David C. Rankin Jun 14 '20 at 08:10
  • @kiner_shah, @David C. Rankin I removed the pointer ```palist final_list = {10, lp};``` but the content is printed as (null), (null). – CipherX Jun 14 '20 at 08:13
  • 1
    Change `palist final_list = {10, *lp};` to `palist final_list = {10, { lp[0], lp[1] } };` – Paul R Jun 14 '20 at 08:28

2 Answers2

6

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;
}
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • That's curious! I wonder why the 4th exception of the operand of the `_Alignof` operator isn't stated in C18 (n2310) anymore. I've always cite quotes without the statement of the `_Alignof` operator as exception. – RobertS supports Monica Cellio Jun 14 '20 at 08:48
  • That is curious. I'll have to read up on that and reduce the number of exceptions `:)` – David C. Rankin Jun 14 '20 at 08:50
  • I wanted to start asking about that but I just found https://stackoverflow.com/questions/51803814/why-is-alignof-missing-from-the-rule-about-converting-an-array-to-a-pointer – RobertS supports Monica Cellio Jun 14 '20 at 08:53
  • 1
    @RobertSsupportsMonicaCellio -- thank you. I'm glad Eric asked the question and I"m glad ex answered -- I would not have sussed out the fine points of the *type name* / *expression* argument being the reason that `_Alignof` disappeared from the paragraph. Correction `"(subject to 3-exceptions not relevant here... if using the C18 standard)"` ... `:)` – David C. Rankin Jun 14 '20 at 08:59
-1

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

0___________
  • 60,014
  • 4
  • 34
  • 74