CodeWithPride
CodeWithPride

Reputation: 123

C-Array of Pointers different ways of indexing

#include<stdio.h>
#include<string.h>

main () {
    char *line[5];
    int i;
    line[0] = "line 1";
    line[1] = "line 2";
    line[2] = "line 3";
    line[3] = "line 4";
    line[4] = "line 5";

    char *p;
    p=line[2];
    //*p = *(p+2);  //gives error as segmentation fault.
    printf("\n coming here : %s",*line); //works fine
    printf("\n coming here : %s",*line++); //gives error "invalid increment in main"
    printf("\n coming here : %s",*(line+2)++); //error, i assumed it will work as *(line+2) is also a pointer
    printf("%c",*(line[4]+1));//works, prints character 'i'
    printf("%c",**(line+4));//segmentation error, i assumed it to print character 'l'
}

I was trying this program and faced few errors as I have mentioned in the comments beside each line of code.

with char *line[5] i was trying to achieve a array of pointers each pointer element of this array pointing to a string.

Please help me clarify what all I am doing wrong here. Thanks.

Edit 1:

I have included only part of the example, please see the writelines function. Rest of this example is pretty straight forward this did not include it.

#define MAXLINES 5000 /* max #lines to be sorted */ 
char *lineptr[MAXLINES]; /* pointers to text lines */

int readlines(char *lineptr[], int maxlines)
{
    int len, nlines;
    char *p, line[MAXLEN];
    nlines = 0;
    while ((len = getline(line, MAXLEN)) > 0)
        if (nlines >= maxlines || p = alloc(len) == NULL) return -1;
        else {
            line[len-1] = '\0'; /* delete newline */ strcpy(p, line);
            lineptr[nlines++] = p;
        }
    return nlines;
}

/* writelines: write output lines */
void writelines(char *lineptr[], int nlines)
{
    while (nlines-- > 0)
        printf("%s\n", *lineptr++); // this is where they are incrementing array, which you said is incorrect.
}

Edit 2:

main(int argc, char *argv[])
{
    char *line[] = {"linawee 1", "lipe 2", "lint 3", "linr 4"};
    while (--argc > 0) //command line input has same number of elements as 'line'
    {
        printf("%s%s", *++argv, (argc > 1) ? " " : ""); //works just fine.
        printf("%s", *++line); //error
    }
}

Please explain the above prog, why it works for one and gives error for other. Thanks.

Upvotes: 0

Views: 309

Answers (4)

Bill Lynch
Bill Lynch

Reputation: 82026

So, let's iterate through the errors:

Line 1:

*p = *(p+2);

You're modifying a string literal. That's not allowed.

Line 2:

printf("\n coming here : %s", *line);

*line will result in the same value as line[0], so this all makes sense.

Line 3:

printf("\n coming here : %s", *line++);

line is an array. You're not allowed to increment arrays. So line++ is invalid.

Line 4:

printf("\n coming here : %s", *(line+2)++);

This actually means:

printf("\n coming here : %s", *(line + 2);
(line + 2) = (line + 2) + 1;

Which is invalid, because you can't assign to line + 2.

Line 5:

printf("%c", *(line[4]+1));

Yep thats fine. We take the string at index 4, and then grab the character in it at index 1.

Line 6:

printf("%c", **(line+4));

This should work fine. It's not clear why you are getting an error.

With regards to edit 1:

void func(char *lineptr[]) {
    *lineptr++;
}

For whatever reason, C allows you to use array notation during function calls. In this case, when you have a function parameter of: char *lineptr[], it is treated as char **lineptr.

Therefore, in this case, you're actually incrementing a pointer, not an array, which is why it's allowed.

Note however, that the increments to the pointer are only visible inside the function. That is, if I do:

int main() {
    char * arr[] = {"hi", "how", "are", "you"};
    inc(arr);
    // arr[0] still points to "hi"
}

void inc(char *arr[]) {
    // arr[0] points to "hi"
    arr++;
    // arr[0] now points to "how"
}

With regards to edit 2:

char *line[] = {"linawee 1", "lipe 2", "lint 3", "linr 4"};
printf("%s", *++line);

You're incrementing an array. You're not allowed to do that. You certainly could do:

printf("%s", line[3]);
printf("%s", *(line + 3)

Upvotes: 4

Vlad from Moscow
Vlad from Moscow

Reputation: 311146

String literals may not be changed though in C they have types of non-const character arrays. In this statement

//*p = *(p+2);  //gives error as segmentation fault

you are trying to change the string literal pointed by p.

As for other errors then arrays in expressions are converted to rvalue of pointers to the first element of arrays. You may not increase an rvalue. For it would be clear then for example expression

(line+2)++

in fact is equivalent to the following code

int x = 0;

( x + 2 )++;

Here the compiler will issue an error because expression ( x + 2 ) is not a lvalue

Upvotes: 1

Evan Sebastian
Evan Sebastian

Reputation: 1744

You have one problem here

You are trying to assign an rvalue (layman terms: value that should be in the right side of equation, and constants that you should not modify)

#include<stdio.h>
#include<string.h>

int main () {
    char *line[5];
    line[0] = "line 1";
    line[1] = "line 2";
    line[2] = "line 3";
    line[3] = "line 4";
    line[4] = "line 5";
    char *p;
    p=line[2];
//  *p = *(p+2);  // *p is a gives you  a character, this means you are trying to assign character with character?
    p = p + 2; // correct way
    printf("%s\n", p); // outputs: "ine 3", expected
    printf("coming here : %s\n",*line); // this is fine
//    printf("\n coming here : %s",*line++); //  Same reason as above and below
//    printf("\n coming here : %s",*(line+2)++); //*(line + 2)++ means *(line + 2) = *(line + 2) + 1 => see the error?
    printf("%c\n",*(line[4]+1)); //works, prints character 'i'
    printf("%c\n",**(line+4));// this prints l on my machine and is valid.
    return 0;
}

Upvotes: 0

Lantay77
Lantay77

Reputation: 21

See: lvalue required as increment operand

line is not a pointer to dynamic memory, it is an array declared on the stack. So line++ is invalid.

Upvotes: 2

Related Questions