2

I'm having an entry level C pointer problem... Let's say I have two strings and I want to print them. What am I misunderstanding in the code below?

void print_array(char **array[]) {
    int i = 0;
    while((*array)[i] != NULL) {
        printf("%s\n", (*array)[i++]);
    }
    return;
}

int main(int argc, char** argv) {
    char str1[] = "hello";
    char str2[] = "world";
    char **array = {str1, str2};

    print_array(&array);
    return (EXIT_SUCCESS);
}

For my code to work I need to access the array like it is in print_array

9
  • What is your question? Commented Sep 12, 2014 at 3:40
  • Sorry I should have said the data in array isn't correct. And at runtime it says Seg. Fault Commented Sep 12, 2014 at 3:41
  • I assume you might want something like print_array(char** array) and char** array = {str1, str2, NULL}; print_array(array); Commented Sep 12, 2014 at 3:43
  • Check the fix here ideone.com/a5PZk0 Commented Sep 12, 2014 at 3:46
  • You know, both your return-statements are superfluous... Also, there's no percentage in normalizing a value in a boolean context. Commented Sep 12, 2014 at 3:49

4 Answers 4

3

Another take on it (Much more refactoring).

Bugfixes:

  • Corrected confusion what should be dereferenced and how in print_array (Don't aspire to 3-star-programming, unless you must)
  • Added the missing sentinel-0 in to the array passed from main to print_array

Other changes:

  • Removed superfluous return-statements (main has an implicit return 0; at the end)
  • Removed superfluous checks for unequality to 0 / NULL
  • Removed one level of indirection from print_array
  • Use of const in print_array where appropriate
  • Eliminated counter-variable in print_array
  • Used a constant compound-literal in main (Needs C99)
#include <stdio.h>

void print_array(const char *const array[]) {
    while(*array)
        printf("%s\n", *array++);
}

int main() {
    print_array((const char*[]){"hello", "world", 0});
}

See here on coliru


Undoing the cleanup steps changing the signature of print_array:

#include <stdio.h>

void print_array(char **array[]) {
    for(char** p = *array; *p; p++)
        printf("%s\n", *p);
}

int main() {
    print_array(&(char**){(char*[]){"hello", "world", 0}});
}

Live on coliru

Sign up to request clarification or add additional context in comments.

Comments

2

There's one too many *'s in print_array. It ought to be this:

void print_array(char *array[]) {
    int i = 0;
    while(array[i] != NULL) {
        printf("%s\n", array[i++]);
    }
}

That makes calling it straightforward. Change char **array to char *array[]. And don't forget to include a NULL entry at the end of the array.

int main(int argc, char** argv) {
    char str1[] = "hello";
    char str2[] = "world";
    char *array[] = {str1, str2, NULL};

    print_array(array);
    return EXIT_SUCCESS;
}

On the other hand, if you're not supposed to modify print_array, then that's annoying. You'll need another variable to hold array's address temporarily.

char *array[] = {str1, str2, NULL};
char **p = array;

print_array(&p);

That's why I say there's one too many *'s in print_array.

Comments

1

since you're dealing with arrays, please pass in the number of array members to print_array. The code above is UB.

To fix your code:

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

int main(int argc, char** argv) {
    char str1[] = "hello";
    char str2[] = "world";
    char *arr[] = {str1, str2};

    print_array(arr, 2);
    return (0);
}

2 Comments

Being more specific, the original code is UB because it iterates off the end of the array. OP perhaps expected that reading off the end of an array would give 0 or equivalent; of course it doesn't.
the extra level of indirection was not needed in order to just read the array, but it wasn't a mistake either
0

Another way:

#include <stdio.h>
void print_array(char *array[]) {
   int i = 0;
   while (array[i] != 0) {
   printf("%s\n", array[i++]);
}
return;
}

int main(int argc, char** argv) {
    char str1[] = "hello";
    char str2[] = "world";
    char *array[] = {str1, str2, 0};

    print_array(array);
    return 0;
}

7 Comments

@Aniket That's silly. Comparing against 0 is a perfectly fine way of checking for null pointers.
@Deduplicator it IS 0, but comparing it directly AS 0.. seems odd to me. Eyes hurt
@Aniket I think you know NULL and 0 means the same thing in C/C++. Eg. if you have a char pointer or pointer something else ptr, you can do "if (ptr != 0)" or "if (ptr != NULL)" .
@Aniket there is implicit conversion from integer constant expression with value 0 to null pointer
@MattMcNabb I just think NULL is more readable. Just personal preference I guess.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.