2010-03-05 44 views
5

considere las siguientes afirmaciones:Aritmética de punteros y matrices: ¿qué es realmente legal?

int *pFarr, *pVarr; 

int farr[3] = {11,22,33}; 
int varr[3] = {7,8,9}; 

pFarr = &(farr[0]); 
pVarr = varr; 

En esta etapa, los dos punteros apuntan al inicio de cada dirección respectiva distribución. Para * Pfarr, actualmente estamos buscando a las 11 y para pVarr *, 7.

Igualmente, si solicito el contenido de cada matriz a través * * Farr y Varr, también tengo 11 y 7.

Así muy bien.

Ahora, probemos pFarr++ y pVarr++. Estupendo. Ahora estamos viendo 22 y 8, como se esperaba.

Pero ahora ...

Tratando de moverse hacia arriba y farr++varr++ ... y obtenemos "tipo incorrecto de argumentos para incrementar".

Ahora, reconozco la diferencia entre un puntero de matriz y un puntero normal, pero dado que su comportamiento es similar, ¿por qué esta limitación?

Esto me resulta aún más confuso cuando también considero que en el mismo programa puedo llamar a la siguiente función de una manera aparentemente correcta y de otra manera incorrecta, y obtengo el mismo comportamiento, aunque en contraste con lo que sucedió en el código publicado arriba?

working_on_pointers (pFarr, farr); // calling with expected parameters 
working_on_pointers (farr, pFarr); // calling with inverted parameters 

.

void working_on_pointers (int *pExpect, int aExpect[]) { 

    printf("%i", *pExpect); // displays the contents of pExpect ok 
    printf("%i", *aExpect); // displays the contents of aExpect ok 

    pExpect++;    // no warnings or errors 
    aExpect++;    // no warnings or errors 

    printf("%i", *pExpect); // displays the next element or an overflow element (with no errors) 
    printf("%i", *aExpect); // displays the next element or an overflow element (with no errors) 

} 

Podría alguien ayudarme a entender por qué los punteros de la matriz y los punteros se comportan de manera similar en algunos contextos, pero diferentes en otros?

Muchas gracias.

EDIT: Noobs como yo podrían beneficiarse más de este recurso: http://www.panix.com/~elflord/cpp/gotchas/index.shtml

+0

' Tratar de moverse hacia arriba y Farr ++ ++ Varr ... y obtenemos" tipo incorrecto de argumento para aumentar, incrementando de una matriz no está permitido, es todo. Y no necesita el paréntesis en & (farr [0]);) ¡Los punteros son __NOT__ arrays! –

+2

"Reconozco la diferencia entre un puntero de matriz y un puntero normal". Aparentemente, tu no. No existe el "puntero de matriz". Array no es un puntero, punto. No puedes incrementar una matriz. – AnT

+1

esto es cierto. sin embargo, cuando se considera que el compilador reduce las matrices entrantes a los punteros dentro de las funciones, entonces se puede ver cómo un novato pensaría que se estaba incrementando una matriz, cuando en realidad era un puntero. – bitcruncher

Respuesta

7

La diferencia se debe a que para farr++ tener ningún efecto, en algún lugar el compilador tendría que almacenar esa farr evaluará a la dirección del segundo elemento de la matriz. Pero no hay lugar para esa información. El compilador solo asigna lugar para enteros 3.

Ahora cuando declara que un parámetro de función es una matriz, el parámetro de función no será una matriz. El parámetro de función será un puntero. No existen parámetros de la matriz en C. Así que los siguientes dos declaraciones son equivalentes

void f(int *a); 
void f(int a[]); 

No siquiera importa qué número se pone entre los corchetes - ya que el parámetro realmente será un puntero, el "tamaño" es solo ignorado

Ésta es la misma para las funciones - los dos siguientes son equivalentes y tienen un puntero a función como parámetro:

void f(void (*p)()); 
void f(void p()); 

Si bien se puede llamar tanto un puntero de función y una función (lo que se utilizan similares), también no ser capaz de escribir a una función, porque no es un puntero - simplemente convierte en un puntero:

f = NULL; // error! 

Mucho de la misma manera que no puede modificar una matriz.

0

Echa un vistazo a esta respuesta que publiqué en relación con las diferencias entre punteros y matrices aquí en SO.

Espero que esto ayude.

1

Intentando incrementar farr o varr falla porque ninguno de ellos es un puntero. Cada uno es una matriz. El nombre de una matriz, cuando se evalúa por sí mismo (excepto como el operando del operador sizeof o address-of) evalúa a un valor (un valor r) que es del tipo correcto para asignar a un puntero. Intentar incrementarlo es como intentar incrementar 17. Puede incrementar un int que contiene el valor 17, pero el incremento de 17 no funcionará. El nombre de una matriz es bastante así.

En cuanto a su segunda parte, es bastante simple: si intenta declarar un parámetro de función de tipo de matriz, el compilador lo "ajusta" silenciosamente a un tipo de puntero. Como tal, en su working_on_pointers, aExpect y pExpect tiene exactamente el mismo tipo. A pesar de la notación de estilo de matriz, ha definido aExpect como el tipo 'puntero a int'. Como los dos son iguales, se espera que actúen de la misma manera.

-2

necesita comprender el concepto básico de matrices.

cuando se declara un array es decir

int farr[] 

en realidad se está declarando un puntero a esta declaración

const int * farr 

es decir; un puntero "constante" a entero. así que cuando haces farr ++, en realidad estás intentando agregar un puntero que es constante, por lo tanto, los compiladores te dan un error.

si necesita comprender, intente declarar un puntero con la declaración anterior y no podrá hacer la aritmética que es legal en los punteros normales.

P.S: ha estado en silencio un tiempo he codificado en C, así que no estoy seguro de la sintaxis exacta. pero la línea de fondo es la diferencia entre un puntero y un puntero constante.

+0

Esto simplemente está mal - farr no es un puntero de ningún tipo - es una matriz, cuyo valor puede convertirse implícitamente en un puntero, pero ya no es la matriz (o farr). –

+0

Las matrices no son punteros. –

5

En C, usted no puede asignar a matrices.Por lo tanto, dado:

T data[N]; 

donde T es un tipo y N es un número, no se puede decir:

data = ...; 

Por todo lo anterior, y que data++; está tratando de asignar a data, se obtiene la error.

Hay una regla simple en C sobre matrices y punteros. Es que, en contextos de valor, el nombre de una matriz es equivalente a un puntero a su primer elemento, y en contextos de objetos, el nombre de una matriz es equivalente a una matriz.

El contexto del objeto es cuando toma el tamaño de una matriz usando sizeof, o cuando toma su dirección (&data), o en el momento de la inicialización de una matriz. En todos los demás contextos, estás en contexto de valor. Esto incluye pasar una matriz a una función.

lo tanto, su función:

void working_on_pointers (int *pExpect, int aExpect[]) { 

es equivalente a

void working_on_pointers (int *pExpect, int *aExpect) { 

La función no se puede saber si se aprobó una matriz o un puntero, ya que todo lo que se ve es un puntero.

Hay más detalles en las respuestas a las siguientes preguntas:

Véase también esta parte de C for smarties sitio web, que está muy bien escrito.

+0

ya había elegido una respuesta antes de ver esto, ¿espero que se conforme con un voto popular? – bitcruncher

+0

@bitcruncher: sin preocupaciones. Mientras entiendas lo que está pasando. –

-1

bien, puedo estar equivocado. pero las matrices y punteros se pueden usar alternativamente.

int * ptr = (int *)malloc(2* sizeof(int)); 
ptr[0]=1; 
ptr[1]=2; 

printf ("%d\n", ptr[0]); 
printf ("%d\n", ptr[1]); 

aquí he declarado un puntero y ahora lo estoy tratando como una matriz.

además:

Como consecuencia de esta definición, no hay diferencia aparente en el comportamiento de la "matriz subíndice" operador [] tal como se aplica a las matrices de y punteros. En una expresión del forma un [i], la matriz de referencia "a" se descompone en un puntero, siguiendo la regla anterior , y luego se subscribe al igual que una variable de puntero en la expresión p [i] (aunque los accesos de memoria eventuales serán diferentes, como se explicó en la pregunta 2.2). En cualquier caso, la expresión x [i] (donde x es una matriz o un puntero ) es, por definición, idéntica a a * ((x) + (i)).

referencia: " 'http://www.lysator.liu.se/c/c-faq/c-2.html

+0

ahora considere el siguiente código \t int arr [5] = {1,2,3,4,5}; \t int * ptr = arr; Acabo de asignar el valor de "arr" var a "ptr" .. .. No estoy pidiendo explicilty copiar la dirección del 0º elemento. dado que el nombre de la matriz es la dirección del primer elemento de la matriz, es decir, la declaración anterior es idéntica a int * ptr = & arr [0]; –

+0

Por favor refiérase a esto también: http://www.google.ca/url?sa=t&source=web&ct=res&cd=8&ved=0CC8QFjAH&url=http%3A%2F%2Fdeneb.cs.kent.edu%2F~mikhail % 2Fclasses% 2Fioop.f00% 2FL19pointers.pdf y ei = w2yQS6-BNZOQNsHOhZEN y USG = AFQjCNHxqgxPgdzwqbiHqPpRXktudJ-4ZG y SIG2 = FzIepm58ihz8mWoksFXISA y refieren a la caja "nombres de matriz y punteros constantes" –

+0

uno más referece: http://www.fredosaurus.com/ notes-cpp/arrayptr/26arraysaspointers.html –

Cuestiones relacionadas