3

The s++ is a valid when it is in a function,

void f(char s[]) {
  s++; // Why it works here?
}

But it isn't when it is in main function. It is wired to me since it has the exactly same data type.

void main() {
  char s[] = "abc";
  s++;  // wrong because it is a const value.
}

Why is that?

canoe
  • 1,273
  • 13
  • 29
  • `char *s[] = "abc";` is invalid -- you're assinging a string (array of `char`) to an array of `char*`. – Frxstrem Apr 17 '14 at 03:52
  • sorry, the typo is fixed. – canoe Apr 17 '14 at 03:57
  • [explained here](http://stackoverflow.com/questions/22677415/why-do-c-and-c-compilers-allow-array-lengths-in-function-signatures-when-they/22677793#22677793) – M.M Apr 17 '14 at 03:58

1 Answers1

7

That is because the function parameter s is not a character array, but a pointer to a character. You cannot pass an array to a function. What actually gets passed is a pointer to the first element of the array. Arrays are not first-class objects in C in this sense. Therefore, the below two function prototypes are equivalent -

void f(char s[]);
// equivalent to
void f(char *s);

This means s can contain the address of any character.

void f(char s[]) {
  // s is a pointer to a character.
  // s++ is fine. evaluates to s and
  // makes s point to the next element
  // in the buffer s points to.
  s++; 
  return *s;
}

However, the following statement defines s to be a array and initializes it with a string literal.

char s[] = "abc";

Arrays and pointers are different types. The array s is bound to a memory location allocated on the stack. It cannot be rebound to a different memory location. Please note the difference between changing the value of a variable and changing the memory location the variable's name is bound to. In the above function, you are only changing the content of s, but s itself always refers to a fixed memory location allocated on the stack.

s++;  // in main

The above statement in the main function evaluates to the base address of the array s, i.e., to &s[0] and its side effect is to change the content of s. Changing the content of s means binding the variable s to a different memory location which is always an error. Any variable will always refer to the same memory location during its lifetime. Its content can however be changed but that's different.

int main(void) {
  // s is an array. Arrays and pointers are
  // different types. initialize s with the
  // characters in the literal "abc"

  char s[] = "abc";
  // equivalent to
  // char s[] = {'a', 'b', 'c', '\0'};

  // illegal operation because s is an array.
  // s is bound to a fixed memory location and
  // cannot be changed.
  s++;
}
ajay
  • 9,402
  • 8
  • 44
  • 71
  • +1. Nice explanation. One query, `void f(char s[]); // equivalent to void f(char *s);` are they exactly same? Then why to use `[]`? – Pranit Kothari Apr 17 '14 at 04:13
  • 1
    @pranitkothari It's just for readability. The compiler *sees* the two prototypes as the same. – ajay Apr 17 '14 at 04:17