3

I have a function with the following signature:

void foo (char **bar);

'bar' is an array of strings with an unknown length.

I need to write a loop checking if every string in 'bar' holds some property, without knowing how many elements are in this array.

I've seen multiple articles saying that this is easy if my signature is either of the following:

void foo (char *bar[LENGTH]);
void foo (char bar[LENGTH01][LENGTH02]);

EDIT: My original question had both of these signatures not contain a hash-defined length, they have been added for clarity.

(I could get the length of the above through sizeof(bar)/sizeof(bar[0])).

Unfortunately, the signature of this function is already defined, and I can't modify it.

Is it still possible to create (for example) a for loop which goes through each string of this array, or is this impossible?

Jinan Dangor
  • 142
  • 7
  • Please refer this: https://stackoverflow.com/questions/6641577/how-do-i-iterate-over-a-pointer-to-a-pointer – fiveelements Jul 22 '19 at 05:22
  • 4
    You _need_ to pass the number of rows in the array as an argument – Spikatrix Jul 22 '19 at 05:28
  • 5
    ... or there needs to be a [sentinel](https://en.wikipedia.org/wiki/Sentinel_value) (e.g. a NULL pointer) at the end of the list. – user3386109 Jul 22 '19 at 05:29
  • In the context of a function's parameter definition `char**bar` and `char *bar[]` are the same and `char bar[][]` being an incomplete type is invalid. – alk Jul 22 '19 at 05:41
  • @fiveelements This post clearly doesn't answer my question. – Jinan Dangor Jul 22 '19 at 05:42
  • "*'bar' is an array of strings*" No, `bar` is a pointer to a pointer to `char`, nothing more, nothing less. – alk Jul 22 '19 at 05:44
  • 2
    The key being that a parameter of `char **bar` simply takes a *pointer-to-pointer to char*. There is no way to be sure that the first pointer points to valid data unless (1) the number of strings is passed as a second parameter (or is a global) or (2) the array of pointers is terminated with a *sentinel* `NULL` as is the case with `argv` in `int main (int argc, char **argv)`. – David C. Rankin Jul 22 '19 at 05:46
  • @AnttiHaapala While they aren't taking input from a function, [multiple articles](https://stackoverflow.com/questions/6812242/defining-and-iterating-through-array-of-strings-in-c) clearly [believe](https://stackoverflow.com/questions/34134074/c-size-of-two-dimensional-array) that given something of that type you can loop through them (although they have defined lengths, so I've added this to my question in case this was your objection). If they're wrong, how about fixing them instead of blaming me for using this website? – Jinan Dangor Jul 22 '19 at 05:51
  • @alk I was describing semantics for clarity, not syntax. 'bar' was being used as an array of strings, which would be semantically, but not syntactically, different from a 2d array of characters. For your first comment, I've updated the function signatures to something I (believe) is more appropriate (while they aren't central nor necessary to answering my question). – Jinan Dangor Jul 22 '19 at 05:56
  • Your update changed your question **significantly**. Not so good, as it renders most of the comments and answer(s) ununderstandable. You better added this to your question instead of replacing stuff. – alk Jul 22 '19 at 05:59
  • 3
    @JinanDangor The whole scenario changes when you pass arrays to a function. When you pass a two dimensional array to a function, it "decays" (gets converted) to a pointer to its first element, that is, a pointer the the first row of the two dimensional array. Due to this conversion, you cannot use the `sizeof` trick to get the size of the array unless, as said in the comments above, you 1) Pass the size as a parameter 2) Use a sentinel value e.g: `NULL` – Spikatrix Jul 22 '19 at 06:00
  • @alk I really don't want to clutter the question with irrelevant blocks of code (given how irrelevant the blocks of code are, as is, to actually answering my question), but I've updated the 'EDIT' note to more explicitly state the changes I made so these comments are more clear. – Jinan Dangor Jul 22 '19 at 06:11
  • 1
    I have always found it good to ask yourself ”what does the compiler know at this point in the code”, then it becomes easy to answer these sort of questions. – Fredrik Jul 22 '19 at 06:14

1 Answers1

4

While you can check when a single string ends ( for example bar[0] ) by looking at the string terminator \0 or using strlen function, you cannot check where the array of strings ends. Unless the last one has been initialized with NULL.

In that case you can write:

char* str;
int i = 0;
while ((str = bar[i]) != NULL){
    printf("%s\n",str);
    i++;
}
Tony Barletta
  • 357
  • 1
  • 7