Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pointer to array with const qualifier in C & C++

Consider following program:

int main() {     int array[9];     const int (*p2)[9] = &array; } 

It compiles fine in C++ (See live demo here) but fails in compilation in C. By default GCC gives following warnings. (See live demo here).

prog.c: In function 'main': prog.c:4:26: warning: initialization from incompatible pointer type [enabled by default]      const int (*p2)[9] = &array; 

But If I use -pedantic-errors option:

gcc -Os -s -Wall -std=c11 -pedantic-errors -o constptr constptr.c 

it gives me following compiler error

constptr.c:4:26: error: pointers to arrays with different qualifiers are incompatible in ISO C [-Wpedantic] 

Why it fails in compilation in C but not in C++? What C & C++ standard says about this?

If I use const qualifier in array declaration statement it compiles fine in C also. So, what is happening here in above program?

like image 343
Destructor Avatar asked Dec 28 '15 06:12

Destructor


People also ask

What is const qualifier in C?

The const qualifier explicitly declares a data object as something that cannot be changed. Its value is set at initialization. You cannot use const data objects in expressions requiring a modifiable lvalue. For example, a const data object cannot appear on the lefthand side of an assignment statement. C only.

Can a pointer point to a const?

A pointer to a non-const value can change the value it is pointing to. These can not point to a const value.

What is the use of const qualifier?

The const keyword can be used as a qualifier when declaring objects, types, or member functions. When qualifying an object, using const means that the object cannot be the target of an assignment, and you cannot call any of its non-const member functions.

Why do we require const qualifier in C?

We use the const qualifier to declare a variable as constant. That means that we cannot change the value once the variable has been initialized. Using const has a very big benefit. For example, if you have a constant value of the value of PI, you wouldn't like any part of the program to modify that value.


1 Answers

GCC-gnu

In GNU C, pointers to arrays with qualifiers work similar to pointers to other qualified types. For example, a value of type int (*)[5] can be used to initialize a variable of type const int (*)[5]. These types are incompatible in ISO C because the const qualifier is formally attached to the element type of the array and not the array itself.

C standard says that (section: §6.7.3/9):

If the specification of an array type includes any type qualifiers, the element type is so- qualified, not the array type.[...]

Now look at the C++ standard (section § 3.9.3/5):

[...] Cv-qualifiers applied to an array type attach to the underlying element type, so the notation “cv T,” where T is an array type, refers to an array whose elements are so-qualified. An array type whose elements are cv-qualified is also considered to have the same cv-qualifications as its elements. [ Example:

 typedef char CA[5];  typedef const char CC;  CC arr1[5] = { 0 };  const CA arr2 = { 0 }; 

The type of both arr1 and arr2 is “array of 5 const char,” and the array type is considered to be const- qualified. —endexample]

Therefore, the initialization

const int (*p2)[9] = &array;   

is assignment of type pointer to array[9] of int to pointer to array[9] of const int. This is not similar to assigning int * to a const int * where const is applied directly to the object type the pointer points to. This is not the case with const int(*)[9] where, in C, const is applied to the elements of the array object instead of the object the pointer points to. This makes the above initialization incompatible.

This rule is changed in C++. As const is applied to array object itself, the assignment is between same types pointer to const array[9] of int instead of type pointer to array[9] of int and pointer to array[9] of const int.

like image 157
haccks Avatar answered Oct 06 '22 13:10

haccks