7

I can't seem to wrap my head around a problem. What am I missing?

Consider the following

int main(int argc, char *argv[]) {
    while ( *argv ) {
        printf("argv[] is: %s\n", *argv);
        ++argv;
    }

    return 0;
}

This prints out every value of argv. So a command line such as ./example arg1 arg2 would output the following:

`argv[] is: ./example`
`argv[] is: arg1`
`argv[] is: arg2`

Now consider the following (which I am having trouble with):

int main(void) {
    char *days[] = {
        "Sunday",
        "Monday",
        "Tuesday"
    };
    while ( *days ) {
        printf("day is %s\n", *days);
        *days++;
    }

    return 0;
}

If I try to compile, I get error cannot increment value of type 'char *[3]'

If I change *days++ to (*days)++ it compiles. If I run it, it runs forever and eventually fails with bus error.

However, it does not iterate through every value of days[]. I even tried putting in a Null pointer in the form of '\0' and "\0" in the days array to no effect.

What am I missing?

2
  • ideone.com/GM4wIN Commented Nov 12, 2016 at 16:16
  • See ++argv; vs *days++;! Commented Nov 12, 2016 at 16:24

4 Answers 4

7

You have several errors in your code:

  1. There is difference between variable argv and constant days. Variable can be changed, constant array label - cannot.

  2. In your array, terminator NULL is missing at the end of the array.

  3. *days++; is senseless in this case. This is a dummy and returns value of days, and increment days thereafter. It is enough to just use days++.

Thus, your code must be like:

#include <stdio.h>

int main(void) {
    char *days[] = {
        "Sunday",
        "Monday",
        "Tuesday",
        NULL
    };

    // Your style
    char **d = days;
    while ( *d ) {
        printf("day is %s\n", *d);
        d++;
    }

    // Or, more "scholastic" code
    for(const char **d = days; *d; d++)
        printf("day is %s\n", *d);

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

4 Comments

ok, so when I declared char *days[] I didn't actually create a pointer, i created an array? is that why you had to put the array in a pointer named *d ? so I can thus use pointer arithmnatic?
Yes. If you would like know details, build your program with option -S, and review assembly code.
days is a variable, not a constant. There is a rule that array variables cannot be incremented.
const char **d = days; is an error, there is no implicit conversion from char ** to const char ** . To use that code you would also have to declare the array as const char *days[] .
6

The argv[] structure contains a null pointer as the last entry which is why your code works. You can add a null pointer to your data structure. You also need to realize that argv is a parameter (just like a local variable) that points to the internal data structure holding the command line arguments. You need to create a similar local variable that can iterate through the array.

Here is a solution:

#include <stdio.h>
int main(void) {
    char *days[] = {"Sunday", "Monday", "Tuesday", 0 };
    char **v = days;

  while (v) {
    printf("day is %s\n", *v);
    v++;
  }

  return 0;
}

2 Comments

ok, why the double asterix **v? is it a pointer to a pointer? i've yet to see ** in any examples
@fizzydrink: In your code you have a function parameter definition char *argv[], which its context is the same as char ** argv. Just replace it, recompile and become enlightened.
1

Instead of trying to increment the character pointer, you should probably loop through each element in the character array.

For example:

char *days[] = {
    "Sunday",
    "Monday",
    "Tuesday"
};
int i;    
for (i = 0; i < 3; i++) 
    printf("day is %s\n", days[i]);

1 Comment

The 3 should perhaps be replaced by sizeof(days) / sizeof(days[0]), or an enumeration constant enum { NUM_DAYS = sizeof(days) / sizeof(days[0]) }; or something similar. Or use a sentinel NULL pointer to mark the end of the data, as with argv when passed to main() — but notice that the arguments to main() are redundant since you could determine argc by iterating through argv (or you could omit the NULL element at the end of argv), but it is more convenient to have the redundancy.
1
  1. days is a 2D character array. Though the name of the array points to the first address, it is not a pointer. You can not do pointer arithmetic on an array name.
  2. while ( *days ) will never become false. You should change the logic.

In the below code I have retained most of your code.

 #include <stdio.h>

    int main(void) {
        char *days[] = {
            "Sunday",
            "Monday",
            "Tuesday"
        };

       for(int i=0; i < 3; i++) {
            printf("day is %s\n", (days[i]));
        }

        return 0;

Comments

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.