-1

I am just starting out with C and I am trying to make an array of 3 strings pass through a function. However, in that function, only 1 string remains and it looks like there isn't even an array. I have tried numerous things already but I can't seem to fix it.

#include <stdio.h>
#define NUM_WORDS 3
#define MAX_WORD_SIZE 64

void printStrings(char words[])
{
    //But now 'words' looks like this: "one"  
    for (int i = 0; i < NUM_WORDS; ++i)
        printf("%s", words[i]);
}

void main()
{
    char words[NUM_WORDS][MAX_WORD_SIZE] = { "one", "two", "three" };
    //At this point the array 'words' looks like this:  
    //{ "one", "two", "three" }
    printStrings(words);
}
Brent
  • 328
  • 4
  • 11
  • Your compiler should warn you about type incompatibility in `printStrings(words);` – UnholySheep Dec 04 '18 at 17:51
  • Hint: You're passing `char**` into a function that takes `char*`. Array vs. array of arrays. – tadman Dec 04 '18 at 17:51
  • 1
    Change `void printStrings(char words[])` to `void printStrings(char *words[])`. Also read [this](https://boredzo.org/pointers/) to learn more about the relationships between arrays and pointers in C. `words` == `&words` == `&words[0]` – torstenvl Dec 04 '18 at 17:52
  • 3
    @torstenvl no, the function should be `void printStrings(char words[][MAX_WORD_SIZE])`. What is being passed is a 2D array, not an array of pointers. – Weather Vane Dec 04 '18 at 17:56
  • @WeatherVane: Fair enough. [C FAQ](http://c-faq.com/aryptr/pass2dary.html) – torstenvl Dec 05 '18 at 07:33

3 Answers3

1

Your declaration of words inside of main is correct, but to pass a two dimensional array to a function, you need to declare it as such in the function. Your current declaration of printWords only declares its parameter as a single dimensional array of characters, which explains why it's not working right.

The minimum required to declare this correctly is as follows:

void printStrings(char words[][MAX_WORD_SIZE])

However, in this case, you have the option of doing this:

void printStrings(char words[NUM_WORDS][MAX_WORD_SIZE])

That has the advantage (and disadvantage) of implying a greater restriction on what can/should be handed to printWords. It's somewhat akin to the difference between:

void function(char foo[])

which takes an arbitrary sized array of characters, and

void function(char foo[FOO_SIZE])

which states that it's expecting an array of FOO_SIZE, no larger and no smaller.

Note that you can only ever elide the outermost (leftmost) dimension, the inner ones are required so the compiler knows the ultimate size of each outer element.

dgnuff
  • 3,195
  • 2
  • 18
  • 32
  • Yes, but including the outermost dimension might mislead a reader into thinking that `NUM_WORDS` is some kind of restriction to a function, or what is passed to it. – Weather Vane Dec 04 '18 at 18:15
  • 1
    Yes, but still `void function(char foo[FOO_SIZE])` places no restrictions on the array length passed or on how it is indexed by the function. – Weather Vane Dec 04 '18 at 18:31
  • I actually already tried this before but I didn't realize it worked. I should also mention that this wasn't my code it was just an example of what I was trying to do. However, you did help me realize that I had already done it the right way before, thanks a lot! – Brent Dec 04 '18 at 18:36
  • @WeatherVane Agreed - adding dimensions in that way does not place any constraints on the compiler. It's for the benefit of code archaeologists who may come across this function four years from now, after I've moved onto another project (or another company), because it attempts to explain what my intentions were when I wrote it. And yes, like all style choices, it is up to the programmer to make the decision whether to use it or not. – dgnuff Dec 04 '18 at 18:41
1

You need:

#include <stdio.h>
#define NUM_WORDS 3
#define MAX_WORD_SIZE 64

static void printStrings(char words[][MAX_WORD_SIZE])
{
    for (int i = 0; i < NUM_WORDS; ++i)
        printf("%s\n", words[i]);
}

int main(void)
{
    char words[NUM_WORDS][MAX_WORD_SIZE] = { "one", "two", "three" };
    printStrings(words);
    return 0;
}

You have a full 2D array; you must specify the size of all dimensions except the first, as shown. This is completely different from an array of pointers (char *words[] = { "four", "five", "six", NULL };). Then the argument type would be char **words, a bit like argv to main() when it takes arguments.

Note that standard C says main() returns an int. Using void is only valid on Windows; everywhere else, it is wrong.

(I use static because the function isn't going to be referenced outside this source file. Many (most) people don't bother with that. I use compiler options to make it necessary.)

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Not directly related to the OP's question, but which compiler and what option to make it "flag" functions that should be static for scope reasons? I agree that sounds a useful thing to do. – dgnuff Dec 04 '18 at 18:14
  • 1
    @dgnuff: I use `-Wmissing-prototypes -Wstrict-prototypes` with GCC. The missing prototypes triggers a warning about free functions like `printStrings()` when there isn't a prototype in scope before it is defined. If the function will be used outside this source file, there should be a header that declares it (and that header should be included where it is defined and where it is used). If it won't be used outside the source file, then it should be defined `static`. You can optionally have a `static` declaration at the top of the file and the function definition further down the file. – Jonathan Leffler Dec 04 '18 at 18:17
  • 1
    @dgnuff: The strict prototypes rejects `int main()` and any other function not defined with a formal prototype, including function pointers defined without a prototype. – Jonathan Leffler Dec 04 '18 at 18:18
1

Just change the function parameter to char char words[][MAX_WORD_SIZE]:

#include <stdio.h>
#define NUM_WORDS 3
#define MAX_WORD_SIZE 64

void printStrings(char words[][MAX_WORD_SIZE])
{
    //But now 'words' looks like this: "one"  
    for (int i = 0; i < NUM_WORDS; ++i)
        printf("%s", words[i]);
}

void main()
{
    char words[NUM_WORDS][MAX_WORD_SIZE] = { "one", "two", "three" };
    //At this point the array 'words' looks like this:  
    //{ "one", "two", "three" }
    printStrings(words);
}
Leandro Lima
  • 1,140
  • 3
  • 24
  • 42