2010-01-22 16 views
13

Teniendo en cuenta este código:C puntero aritmética

int *p, *q; 

p = (int *) 1000; 
q = (int *) 2000; 

¿Cuál es q - p y cómo?

+0

¿Necesita la etiqueta de tarea? –

+1

@Paul lo dudo. –

Respuesta

32

En realidad es indefinida, de acuerdo con la norma. No se garantiza que la aritmética del puntero funcione a menos que los punteros estén apuntando a un elemento en, o un poco más allá, de la misma matriz.

La sección pertinente de la norma es 6.5.6: 9 (n1362 proyecto de c1x pero esto no ha cambiado desde c99) que establece:

Cuando se restan dos punteros, ambas al apuntar a los elementos del mismo objeto de matriz, o uno más allá del último elemento del objeto de matriz; el resultado es la diferencia de los subíndices de los dos elementos del conjunto.

Lo más probable es que obtenga 250 si su tipo de datos int es de 4 bytes, pero no hay garantía. El comportamiento indefinido (a diferencia del comportamiento definido por la implementación) significa exactamente eso, indefinido. Cualquier cosa puede suceder, hasta incluir la destrucción total de una gran proporción de espacio-tiempo.

un curso de actualización:

  • comportamiento definido es lo que está dispuesto por la norma. Las implementaciones deben hacer esto para ser conformes.
  • El comportamiento definido por la implementación se deja a la altura de la implementación, pero debe documentar ese comportamiento claramente. Use esto si no le importa demasiado la portabilidad.
  • Un comportamiento no definido significa que cualquier cosa puede pasar. ¡Nunca hagas eso!
+4

Esta es la respuesta correcta, sin embargo, supongo que todos quieren creer que la respuesta será 1000/sizeof (int) de todos modos. ¡Oh bien! –

-7

Como p apunta a un int y así q, q-p será 1000.

+1

dividido por sizeof (int) –

+1

Lo siento, pero esto es incorrecto. –

+0

@Pascal ¿Por qué tenemos que dividirlo por sizeof (int)? – NLV

8

q - p es 250.

2000 - 1000 = 1000 
1000/sizeof(int) = 250 

aritmética de punteros, suponiendo sizeof (int) es 4.


Editar: OK, para aclarar. En C, cuando dos punteros son del mismo tipo, la diferencia entre ellos se define como el número de elementos del tipo apuntado entre ellos. Por ejemplo,

struct foo { int ar[1000]; } big[10]; 
char small[10]; 

struct foo *fs, *fe; 
char *ss, *se; 

fs = &big[0]; fe = &big[9]; 
ss = &small[0]; se = &small[9]; 

fe - fs == se - ss; 

Esto es, la diferencia entre los dos punteros en este caso es el número de elementos de la matriz entre ellos. En este caso, es 0, 1, ... 8 o 9 elementos.

+0

Esto es lo que estaba buscando. No me preocupo por el -1 por mi pregunta. ¿Por qué estás dividiendo 1000/sizeof (int)? – NLV

+0

Será mejor que indique "si sizeof (int) es 4". Eso es porque sizeof (char) es * siempre * 1. – paxdiablo

+0

@paxdiablo: Derecha. Cerebro congelado. –

2

q-p se supone que debe devolver cuántos pasos con incremento debe hacer para pasar de p a . Que es 1000/sizeof(int) e igual a 250. Recuerde que q++ realmente irá al siguiente elemento de tipo int, no en el medio, por lo que debe agregar 4 al valor real del puntero. De ahí el resultado.

2

La respuesta: q-p va a ser 250, asumiendo que usted está en una máquina en una int es de 4 bytes.

El cálculo es:

q - p = 1,000 1000/4 (tamaño de un int) = 250

La idea detrás de él:

La idea detrás de la aritmética de punteros es eso, si tiene un puntero int a 1000 y un puntero int a 2000, y pregunta por la diferencia, usted es no preguntando qué es 2000-1000. Lo que está preguntando es cuántos int puedo encajar entre los dos.

Esto es muy conveniente para todo tipo de operaciones, por ejemplo:

int *i = 100; 
i++; // This is **not** 101, it is 104, cause you actually want the next place an int could fit in memory. 

Esto viene especialmente útil cuando se trata de matrices. Una matriz de ints (definida int arr[10]) básicamente se trata como un puntero. Cuando escribe arr[5], el compilador lo traduce a *(arr + 5), es decir, agrega 5 al int puntero llamado arr, y obtiene el valor en esa dirección.

La razón por la que esto funciona, es porque arr + 5 hace no significa "añadir 5 al valor de arr", que significa "poner todo lo que sea neceassary al valor de arr ir hacia adelante 5 int s", o, más precisamente, "agregue 5 * sizeof(int) al valor de arr"