2010-10-01 15 views
6

Considere el siguiente código:matriz como puntero constante

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

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

Mi pregunta es si arr es un puntero constante, ¿cómo es que puedo enviarlo a una función que no recibe un puntero constante?

El código se compila sin la advertencia de descartar calificadores const.

+0

Quiere decir 'arr []', ¿sí? – sje397

+0

¿Por qué está etiquetado en C#? –

+0

Ese código no se compila. 'arr' no es una matriz. –

Respuesta

7

No se deje engañar por el puntero. Lo mismo vale para enteros de civil:

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? 

En resumen, const se aplica a cada objeto individual. Una copia de un objeto const no necesita ser const también.

10

Mi pregunta es si arr es un puntero const, ¿por qué puedo enviarlo a una función que no recibe un puntero const?

arr (dentro main()) no es un puntero const, es una matriz. Un tipo de matriz decae en un tipo de puntero cuando se pasa a una función.

arr (parámetro) en el interior Increment mantiene una copia de la dirección del argumento arr (pasado por valor de main()).

// // arr ++ ileagal porque es un puntero constante

es ilegal porque es una arr no modificable lvalue.

1

Usted no incrementan la matriz en main(), que incrementar la variable local (parámetro) en Incremento()

-1

Se debe a que la función Increment solamente está cambiando su versión local de arr, arr y en main() scope no se cambia realmente. Por lo tanto, no se tiene en cuenta la const en las variables en términos de parámetros de función.

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 
} 
+2

Compila tu ejemplo. Estás equivocado acerca de 'func (b)' –

+0

... y sobre 'func (c)'. –

+0

Las mezclé accidentalmente, las arreglé ahora. –

0

Mi pregunta es si arr es un puntero constante

No es un puntero const.

Así es como declaras un puntero const.

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

C Standard (C99 6.3.2.1/3) dice "excepto cuando es el operando del operador sizeof o la unario & operador, o es una cadena literal utilizado para inicializar una matriz, una expresión que tiene el tipo '' matriz de tipo '' se convierte en una expresión con el tipo '' puntero al tipo '' que apunta al elemento inicial del objeto de matriz y no es un 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. 

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

+1

"puntero, que no se puede modificar" === "puntero const" (pero no "puntero a const"). En cualquier caso, el nombre de una matriz tiene una conversión implícita a un puntero, pero no es un puntero. –

+0

@Ben: ¿Estás seguro? ¿Puedes explicar más sobre * el nombre de una matriz tiene una conversión implícita a un puntero pero no es un puntero *? No existe el puntero semi-puntero o implícito. Un puntero es solo un puntero. ** Cuando declaras una matriz normalmente, obtienes un puntero gratis. El nombre de la matriz actúa como un puntero al primer elemento de la matriz. ** –

+0

@Plazma, @Ben: gracias, actualizó la respuesta. –

1

El 'arr' dentro de la función es un tipo diferente del 'arr' en main. Usted acaba de darles el mismo nombre.

main's es una matriz y me sorprende que su declaración se compile.Normalmente harías:

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

Pero el 'arr' en la función es solo un puntero simple, por lo que puede incrementarse.

Si se agrega, en el principal,

int *arr2 = arr; 

entonces tendría una mejor arr2 incrementar suerte. O bien, podría agregar un índice que podría incrementarse y usarse para indexar en la matriz de arr.

3

La razón por la que no puede incrementar int arr[] en main es porque no es modificable lvalue. La norma dice:

Un lvalue modificable es un valor-I que no tiene tipo de matriz, no tener un tipo incompleto, no tiene un tipo const cualificado, y si es una estructura o unión, no tiene ningún miembro (incluido, recursivamente, cualquier miembro o elemento de todos los agregados o uniones ) con un tipo const-qualified.

El operador de incremento ++ requiere un valor l modificable (como se modifica). Sin embargo, el puntero en la función Increment es un valor l modificable (no es del tipo de matriz, es un puntero), por lo que es legal allí.

0

arr es un puntero de const de tipo int que contiene la dirección del primer elemento, aquí la dirección del valor 1. const define que la dirección que está contenida en arr no se puede cambiar. Esta declaración Incremento (arr); pasa la dirección que está contenida en arr, que es de tipo int * Es por eso que el compilador no se queja.

Cuestiones relacionadas