views:

176

answers:

8

Hi.

consider the following code:

void Increment(int *arr) {
    arr++;
}

int main() {
    int arr[] = {1,2,3,4,5};
    // arr++  // illegal because its a const pointer
    Increment(arr);   // legal
}

My question is if arr is a const pointer, how come i can send it to a function that doesn't receive a const pointer?
The code compiles without the warning of discarding const qualifiers.

Thank you!!

+12  A: 

My question is if arr is a const pointer, how come i can send it to a function that doesn't receive a const pointer?

arr (inside main() )is not a const pointer, it is an array. An array type decays into a pointer type when passed to a function.

arr (parameter) inside Increment holds a copy of the address of the argument arr (passed by value from main()).

// arr++ // ileagal because its a const pointer

It is illegal because arr is a non-modifiable lvalue.

Prasoon Saurav
+1  A: 

You don't increment the array in main(), you increment the local variable (parameter) in Increment()

Dadam
A: 

It is because the function Increment is only changing its local version of arr, and arr in main() scope is not actually changed. Therefore, const on the variables is disregarded in terms of function parameters.

void func(void* param) {}

int main() {
  void *a;
  void *const b;
  void const *c;
  void const *const d;
  func(a);  // legal
  func(b);  // legal, constantness of variable doesn't matter, because the function can't change it anyway
  func(c);  // illegal
  func(d);  // illegal
}
Alexander Rafferty
Compile your example. You are mistaken about 'func(b)'
Steve Fallows
… and about `func(c)`.
Konrad Rudolph
Accidently mixed them around, fixed now.
Alexander Rafferty
A: 

My question is if arr is a const pointer

Its not a const pointer.

Here's how you declare a const pointer.

const char constArray[] = { 'H', 'e', 'l', 'l', 'o', '\0' };

C Standard (C99 6.3.2.1/3) says "Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue.

int b[100];    // b is an array of 100 ints.
int* p;        // p is a pointer to an int.
p = b;         // Assigns the address of first element of b to p.
p = &b[0];     // Exactly the same assignment as above.

p = b;   // Legal -- p is not a constant.
b = p;   // ILLEGAL because b is a constant, altho the correct type.

Source: http://www.fredosaurus.com/notes-cpp/arrayptr/26arraysaspointers.html

KMan
"pointer, which cannot be altered" === "const pointer" (but not "pointer to const"). In any case, the name of an array has an implicit conversion to a pointer but is not a pointer.
Ben Voigt
@Ben: Are you sure? Can you explain more about *the name of an array has an implicit conversion to a pointer but is not a pointer*? There is no such thing as semi-pointer or implicit pointer. A pointer is just a pointer.**When you declare an array normally, you get a pointer for free. The name of the array acts as a pointer to the first element of the array. **
KMan
@Plazma, @Ben: Thanks, updated the answer.
KMan
@PlaZmaZ, KMan: This question is tagged C++, not C. In C++ arrays, while implicitly convertible to pointers, are distinguishable from pointers in a large number of contexts, including sizeof, typeid, template type inference, function overload matching, one-definition-rule, and probably a few other ways I can't think of right now.
Ben Voigt
A: 

The 'arr' inside the function is a different type from the 'arr' in main. You just gave them the same name.

main's is an array and I'm surprised its declaration compiles. Normally you'd do:

int arr[] = {1,2,3,4,5};

But the 'arr' in the function is just a plain pointer, so it can be incremented.

If you add, in main,

int *arr2 = arr;

Then you'd have better luck incrementing arr2. Or, you could add an index that could be incremented and used to index into the arr array.

Graham Perks
+3  A: 

The reason why you can't increment int arr[] in main is because it's not modifiable lvalue. The standard says:

A modifiable lvalue is an lvalue that does not have array type, does not have an incomplete type, does not have a const-qualified type, and if it is a structure or union, does not have any member (including, recursively, any member or element of all contained aggregates or unions) with a const-qualified type.

The increment operator ++ requires a modifiable lvalue (as it modifies). However the pointer in the Increment function is a modifiable lvalue (it's not of an array type, it's a pointer), which is why it's legal in there.

reko_t
+6  A: 

Don't get fooled by the pointer. The same holds for plain ints:

const int a = 42;
int b = a; // How can I assign a const int to a non-const int?
int c = 4; // Come to think of it, the literal 4 is a constant too
void foo (int x) { std::cout << x; }
foo(a); // How come I can call foo with a const int?

In summary, const applies to each object individually. A copy of a const object doesn't need to be const too.

MSalters
A: 

arr is a const pointer of type int which holds the address of the first element, here the address of value 1. const defines that the address which is contain in arr cannot be changed. This statement Increment(arr); passes the address which is contain in arr, which is of type int * Thats why the compiler does not complain.

sadananda salam