0

So I have this code that I've boiled down so its only purpose is to show the problem I'm having:

typedef struct _TEST {char strarr[3][20];} TEST;

int main(int argc, char *argv[]) {
    char strarr[3][20] = {"some", "test", "strings"};
    TEST test = {.strarr=strarr};

    return 0;
}

When I try to compile it I get this warning:

$ gcc test.c -o test
test.c: In function ‘main’:
test.c:6:26: warning: initialization makes integer from pointer without a
cast [-Wint-conversion]
     TEST test = {.strarr=strarr};
                          ^
test.c:6:26: note: (near initialization for ‘test.strarr[0][0]’)

I've tried googling the error message, but the results I get are all people who are using pointers incorrectly. I don't think I'm using pointers incorrectly. I don't think I'm really even using pointers in this code, but I'm fairly new to C and there's still a lot of things that I don't really understand (how they work or why they're so unintuitive). Especially with strings.

I've also tried googling various phrases along the lines of "assigning a string array in a struct initializer," but none of the results I've found are relevant to my problem.

I did find something maybe relevant when I searched "near initialization for." While it's not specifically relevant to my problem, I did find some useful info: They got the warning because they were initializing the variable incorrectly. But I don't know what I'm doing incorrectly.

Community
  • 1
  • 1
Josie Thompson
  • 5,608
  • 1
  • 13
  • 24
  • 7
    I think the real question is why this compiles at all for you. `char[3][20] strarr;` is not valid C, and all versions of gcc I can find right now properly error out on it, as they should. The correct C declaration would be `char strarr[3][20];`. Are you really sure the code you've posted is the exact code you're compiling? – Dolda2000 Dec 23 '16 at 04:37
  • Since right side `strarr` is treated as a pointer, such initialization is impossible. Use `memcpy` instead. – BLUEPIXY Dec 23 '16 at 04:38
  • or `TEST test; test = *(TEST*)strarr;` – BLUEPIXY Dec 23 '16 at 04:53
  • 1
    Dolda2000 oh whoops that was just a typo when I was copying it over – Josie Thompson Dec 23 '16 at 04:54
  • @BLUEPIXY, how is is `strarr` treated as pointer? Again, I'm fairly new to C. Also what specific lines of code are you talking about? right side `strarr`? – Josie Thompson Dec 23 '16 at 04:56
  • I talk about `.strarr=strarr`. In this part, `strarr` on the right side is treated as a pointer. – BLUEPIXY Dec 23 '16 at 05:01
  • It is?? I had no idea. should I write `.strarr=*strarr` instead, or will that not work the way I expect? – Josie Thompson Dec 23 '16 at 05:03
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/131307/discussion-between-josie-thompson-and-bluepixy). – Josie Thompson Dec 23 '16 at 05:05
  • C will not copy the whole array for you. You must do it yourself. `memcpy` is a standard function you can use to do this. – e0k Dec 23 '16 at 05:05
  • `.strarr=*strarr` will not work as you expect. – BLUEPIXY Dec 23 '16 at 05:06

1 Answers1

1

Because strarr is an array you can't write .strarr = strarr. Because an array is not assignable. So you could do:

test_s test = {
    .strarr = {{strarr[0][0],
                strarr[0][1] /* to strarr[0][x], x is the end of the string '\0' */},
               {0 /* same for strarr[1] */},
               {0 /* strarr[2] */}}};

but it's really painful. So you can use memcpy() instead:

#include <stddef.h>
#include <stdio.h>
#include <string.h>

typedef struct
{
    char strarr[3][20];
} test_s;

int main(void)
{
    char strarr[3][20] = {"some", "test", "strings"};

    test_s test;
    memcpy(test.strarr, strarr, sizeof test.strarr);

    for (size_t i = 0; i < sizeof strarr / sizeof *strarr; i++) {
        printf("%s\n", test.strarr[i]);
    }
}

Or use a pointer of pointer. So test will be valid only if strarr is valid too:

#include <stddef.h>
#include <stdio.h>

typedef struct
{
    char **strarr;
} test_s;

int main(void)
{
    char *strarr[] = {"some", "test", "strings"};

    test_s test = {.strarr = strarr};

    for (size_t i = 0; i < sizeof strarr / sizeof *strarr; i++) {
        printf("%s\n", test.strarr[i]);
    }
}

Or again use a pointer of pointer but allocate the memory so test can live without strarr:

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct
{
    char **strarr;
} test_s;

int main(void)
{
    char *strarr[] = {"some", "test", "strings"};
    size_t const size_strarr = sizeof strarr / sizeof *strarr;

    test_s test = {.strarr = malloc(sizeof *test.strarr * size_strarr)};
    if (test.strarr == NULL) {
        return 1;
    }

    for (size_t i = 0; i < size_strarr; i++) {
        test.strarr[i] = malloc(sizeof *test.strarr[i] * (strlen(strarr[i]) + 1));
        if (test.strarr[i] == NULL) {
            return 1;
        }
        strcpy(test.strarr[i], strarr[i]);

        printf("%s\n", test.strarr[i]);
    }
}

More info about array.

Community
  • 1
  • 1
Stargateur
  • 24,473
  • 8
  • 65
  • 91
  • 1
    thank you so much, I didn't know about arrays being assignable. maybe I need read up a little more on c before trying to develop. – Josie Thompson Dec 23 '16 at 21:50
  • also, are there any style standards for c? like for structs, I've seen all caps but I don't generally like all caps, and I would think to use capital case but that probably wouldn't be good for the sake of confusing with classes – Josie Thompson Dec 23 '16 at 21:56
  • 1
    @JosieThompson struct no need convention because you must write `struct name`. But you can do `name_s` if you want. It's ok to use class convention `struct Name`. – Stargateur Dec 23 '16 at 22:08