0
#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.

Bill Lynch
  • 76,897
  • 15
  • 123
  • 168
CodeWithPride
  • 133
  • 3
  • 14
  • Sometimes you are using correct constructions like `p=line[2];`, but sometimes you are trying to do something very strange. So, what is your problem? Just use standard ways to access elements of array (i.e. `line[i]`) and everything will be ok. – Ilya Jul 11 '14 at 16:36
  • One of the best lines for understanding is `printf("%c",*(line[4]+1));` (here you are getting access to second character of fifth line, because `line[4]` is pointer on fifth string and `+1` increases it (so you get pointer on next character "i")) – Ilya Jul 11 '14 at 16:39
  • note that the syntax `line[i]` is just syntactic sugar for `*(line+i)` – Enzo Jul 11 '14 at 16:39

4 Answers4

4

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)
Bill Lynch
  • 76,897
  • 15
  • 123
  • 168
  • Your transformation of line 4 transforms pre-increment instead of post-increment. Of course, both are invalid for the same reason but I'd suggest you edit it, some beginners in C confuse operator precedence and order of evaluation. – mafso Jul 11 '14 at 17:11
  • @mafso I disagree. If I did a preincrement, I would call printf on `*(line + 3)`, which I don't. The assignment happening before or after the `printf()` call is unspecified. – Bill Lynch Jul 11 '14 at 17:21
  • It happened (if it could happen at all, it's an assignment to a non-lvalue, of course) _after_ the `printf` call. A function call is a sequence point. And what I suggested: `printf("...: %s", *(line + 2); (line + 2) = (line + 2) + 1` (removed `"`, obviously a typo). – mafso Jul 11 '14 at 17:38
  • I think, I was a little vague: Replacing `line + 2` by `l` (and assuming `l` was a modifiable lvalue): `printf("%s", *l++);` would be equivalent to `printf("%s", *l); l++;`, not to `l++; printf("%s", *l);`. – mafso Jul 11 '14 at 17:43
  • @mafso: Yep. I see what you're getting at now. The screwy lvalue confused me. Thanks! (And also thanks for noting the extraneous `"`). – Bill Lynch Jul 11 '14 at 17:44
  • @sharth thanks for this ans, cleared my doubts. I nw recall having read that we cannot increment array pointers with ++, however would 3 have worked if i had used +1 instead of ++? – CodeWithPride Jul 12 '14 at 05:18
  • @sharth : I was trying this by taking que from an example from Dennis Ritchie Ansi C. I will edit the question to add the example i am talking about. Kindly comment on how i went wrong in understanding that example. – CodeWithPride Jul 12 '14 at 05:22
  • @CodeWithPride: I've added some comments about the two edits. – Bill Lynch Jul 12 '14 at 14:21
  • @sharth : thanks for the comments, your comment for edit 1 actually helped understand edit 2 as well .. thanks a lot :) – CodeWithPride Jul 12 '14 at 15:29
2

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.

Community
  • 1
  • 1
Lantay77
  • 21
  • 4
1

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

Vlad from Moscow
  • 265,791
  • 20
  • 170
  • 303
0

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;
}
Evan Sebastian
  • 1,684
  • 14
  • 19