0
void doSmth(char **ar, int lines) {

  ar= (char*) malloc(sizeof(char*) * lines);

  for (int i = 0; i < lines; i++) {
    ar[i] = (char*) malloc(200 + 1);
    for (int j = 0; ar[i][j] != '\0'; j++) {
      printf("%c", ar[i][j]);
    }
    free(ar[i]);
  }

  free(ar);
}

This code seems right to me but nothing happens. There is no error whatsoever. I've tried other ways to iterate over array other than != '/0' part.

Note: The 200 is because a single line cannot be longer than 200 chars long per program requirements.

hex
  • 121
  • 7
  • So you read **whatever** data is there in an uninitialized allocated block, and you ask why anything is happening? Well, the answer is **undefined behavior** -- next .... –  Apr 22 '18 at 07:20
  • There is no array at all in your code... A pointer to pointer to `char` is **not** the same as an array! You would have to become a **three-star** programmer to have the changes you make to `ar` visible back in the calling function. (that's not a compliment) – David C. Rankin Apr 22 '18 at 07:20
  • Looks like you are looking through uninitialised memory for string terminators and then trying to print them as characters. What do you intend this to do? – Yunnosch Apr 22 '18 at 07:21
  • @DavidC.Rankin it's to `char`, but doesn't really matter. You could however say that the pointers point to an array, that wouldn't be wrong. It's just, with this code, you never have the array, just a pointer to it.... –  Apr 22 '18 at 07:22
  • Please read [Do I cast the result of malloc?](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa) – Ed Heal Apr 22 '18 at 07:23
  • @DavidC.Rankin it's still `char`, not int. And what's allocated here **are** arrays, just the result isn't a **2d array** but an **array of pointers to arrays** .... absolute classic here that people don't get the difference between the two ... –  Apr 22 '18 at 07:24
  • Yes, yes, you can index the pointer to pointer to char as a 2D array, but it is **not** an array. (it was my bad on the `int` -- I'm getting old) I'll leave this to your capable hands, it's past my bed time `:)` – David C. Rankin Apr 22 '18 at 07:25
  • @DavidC.Rankin there are arrays in this code, whatever `ar` points to becomes an array of `char *` as soon as it's first written to, see "effective types" in the standard. It's just the 2d array that's nowhere in sight with this code. But well, I might just further confuse the OP with this discussion ... :/ –  Apr 22 '18 at 07:27
  • @FelixPalmen Isn't there a 2d array in the sense that there is an array of strings (lines) which are arrays of chars themselves? – hex Apr 22 '18 at 07:30
  • No, there are not. `ar` is a *pointer-to-pointer* to `char`, The first `malloc` allocates storage for `lines` number of pointers. Each subsequent `malloc` allocates storage for `201` characters and assigns each block to pointer `ar[i]` -- nowhere is there an array. You have pointers and dynamically allocated blocks of memory. (yes, it's a typical dynamically allocated array of chars, but that is just an allocated block accessed via type `char`) – David C. Rankin Apr 22 '18 at 07:30
  • @hex no. A 2d array in C is a contiguous block in memory, indexed using 2 dimensions. What you have is accessed in a way that kind of *looks the same*, still it's one array full of pointers, each pointing to a different array. –  Apr 22 '18 at 07:32
  • @hex btw, the accepted answer on the duplicate should explain your immediate question: it just doesn't make any sense trying to use values from a freshly allocated block, they are indeterminate. –  Apr 22 '18 at 07:33
  • @DavidC.Rankin if you allocate storage for more than a single element, the object you create is **indeed** an array as well. What you get of course is just a pointer to that array. But again, that's details. We don't see a "2d array" here, that's for sure. –  Apr 22 '18 at 07:35
  • Yes, I know what you are saying, and I know we are somewhat splitting hairs here, so don't take this the wrong way. But `char **ar` is just a pointer to pointer. to char. (yes call it an array of pointers, but technically there is no guarantee that the memory each pointer points to will be contiguous in memory.) `char ar[50][201];` would declare an array. Don't forget to point out that by passing `char **ar` to `doSmth` (and not the address of), the function receives a *copy-of* `ar` and any changes made in `doSmith` will not be visible back in the calling function. – David C. Rankin Apr 22 '18 at 07:39
  • When I think Arrays, I think [C11 Standard - 6.7.6.2 Array declarators](http://port70.net/~nsz/c/c11/n1570.html#6.7.6.2). While I agree we generally term `type p* = malloc (sizeof *p * numelements);` an array, but by the semantics of the standard, they are not technically "Arrays", but rather objects of *allocated storage duration*, see [C11 Standard - 6.2.4 Storage durations of objects](http://port70.net/~nsz/c/c11/n1570.html#6.2.4). That was the only point I was trying to make -- not argue with what we both know are loosely called arrays `:)` – David C. Rankin Apr 22 '18 at 07:50

0 Answers0