3

If you had a function which took the following:

void foo(char **arr);

How can you do the following:

void foo(char* x[] = { "hello", "my", "friend" });

If this confuses you, in Java we do this by the following:

public void foo(String[] x);

foo(new String[] { "hello", "my", "friend" });

Currently, I do the following in C which I hate because it looks really ugly:

char* myArr[] = 
    { 
        "hello", "my", "friend"
    };

foo(myArr);
alk
  • 69,737
  • 10
  • 105
  • 255
Hatefiend
  • 3,416
  • 6
  • 33
  • 74
  • 1
    I would kindly advice you to ask the 2nd, totally unrelated question, in a new question. Tip: Make some research first... :) – gsamaras Aug 27 '16 at 03:23
  • Short answer: C is not Java. Some things can't be done in C in the same way as in Java. This is one of them. You will find C programmers who will be thankful that it is not possible to do this in your Java way. – Peter Aug 27 '16 at 03:40

3 Answers3

5

Java and C are different languages with different idioms.

If it were me, I'd refrain from trying [too hard] to coerce C into "Java-like". Embrace each language on its own merits.

For your first example, the "ugly" one, you could use a CPP [C preprocessor] macro--a concept that does not exist in Java:

#define FOO(_av...) \
    do { \
        char *myArr[] = { _av, NULL }; \
        foo(myArr); \
    } while (0)

FOO("hello", "my", "friend");

But, this would probably be regarded by many as "too cute". Better to create a table of some sort.

Whenever Java does a new it is doing a heap allocation [which is slow]. That's partly because everything has to be "on the heap", more or less.

C can do this with malloc, but a good C programmer will try to avoid unnecessary heap allocations because it has globals, statics, and function scoped variables.

Craig Estey
  • 30,627
  • 4
  • 24
  • 48
  • 1
    "But, this would probably be regarded by many as "too cute". ", or too... :P :P :P Anyway, good thing we have an alternative to my answer, +1.. :) – gsamaras Aug 27 '16 at 03:36
5

How can you do the following:

void foo(char* x[] = { "hello", "my", "friend" });

You nearly made it ... ;-)

If doing C99 or newer use a compound literal like this:

foo((char *[]){"hello", "my", "friend"});

Mind that the called function (foo() here) has no clue how many elements the pointer array has, so you want to add a final null-pointer as sentinel:

foo((char *[]){"hello", "my", "friend", NULL});

Example:

#include <stdio.h>
#include <stdlib.h> /* for EXIT_xxx macros */


void foo(char **arr)
{
  while (arr && *arr)
  {
    printf("%s\n", *arr);
    ++arr;
  }
}

int main(void)
{
  foo((char *[]){"hello", "my", "friend", NULL}); /* Mind the final NULL. */

  return EXIT_SUCCESS;
}

This will print:

hello
my
friend

The compound literal is valid until the scope it got defined in is left (main() here). If you want to make sure it gets removed from the stack immediately after its usage put braces around the call to foo() creating a local scope/block:

int main(void)
{
  {
    foo((char *[]){"hello", "my", "friend", NULL}); /* Mind the final NULL. */
  }

  /* The compound literal passed to foo() is already deallocated here, had been 
     removed from the stack. */

  ...
alk
  • 69,737
  • 10
  • 105
  • 255
3

You must be just another victim of the people that start with and then trying to get into , that's why I will answer.

I want to initialize my array inside of that parameter. How can that be done?

You cannot. prior to C99


In general, this is something you could do:

#include <stdio.h>

void foo(char** arr, int size)
{
    int i;
    for(i = 0; i < size; ++i)
        printf("%s\n", arr[i]);
}

void bar(char** arr)
{
    while(*arr)
        printf("%s\n", *arr++);
}

int main(void)
{
    char* x[] = { "hello", "my", "friend" };
    foo(x, 3);

    char* null_terminated[] = { "ShadowRanger", "Correct", NULL };
    bar(null_terminated);

    return 0;
}

where foo() uses the size of the array explicitly, while bar() requires the array to be NULL terminated.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • I'm sorry but it seems you didn't read my question. See where you typed `foo(x, 3)`? I want to initialize my array **inside** of that parameter. How can that be done? – Hatefiend Aug 27 '16 at 03:23
  • 2
    @Hatefiend I did. You cannot. – gsamaras Aug 27 '16 at 03:24
  • Alternative to passing length is to add a `NULL` sentinel to the end of the `char*` array, so `foo` can continue until `arr[i]` is `NULL`. Explicit length is usually better, but sentinels are occasionally useful. – ShadowRanger Aug 27 '16 at 03:25
  • Nor can I declare a function inside of a parameter? – Hatefiend Aug 27 '16 at 03:26
  • 1
    @ShadowRanger updated, what do you think? Smart idea! Hatefiend, no, but you can pass a function pointer, as you already know... ;) – gsamaras Aug 27 '16 at 03:30
  • And C doesn't (except gcc stuff) support local function definitions so I can't even make a local function to pass the pointer into? I ask this because I'm making a HashMap and I am passing the HashCode function in, but it's annoying because the only reason the HashCode function exists is for the HashMap, and it has no place inside the file of which the HashMap variable is allocated in. – Hatefiend Aug 27 '16 at 03:44
  • @Hatefiend check the other answer, if you find something there. For your question, I think the answer is the same. – gsamaras Aug 27 '16 at 03:45
  • "*You cannot*" Sure you can, at least when using >=C99. Please have a look at my answer. – alk Aug 27 '16 at 14:32
  • @alk sure you got my upvote, answer edited! – gsamaras Aug 27 '16 at 17:44