2011-10-06 8 views
5

tengo la siguiente aplicación de prueba:¿Por qué un char * se trata igual que un char ** en C?

#include <stdlib.h> 
#include <string.h> 
#include <stdio.h> 

int main(void){ 
    char buf[512]; 
    buf[0]= 0x1; 
    buf[1]= 0x2; 
    char *temp1 = &buf; 
    char *temp2 = buf; 
    char *temp3 = &buf[0]; 
    printf("temp1:%p, temp2:%p, temp3:%p\n",temp1,temp2,temp3); 
    printf("0 = %d, %d, %d\n",temp1[0],temp2[0],temp3[0]); 
    printf("1 = %d, %d, %d\n",temp1[1],temp2[1],temp3[1]); 
    return; 
} 

Compila con una advertencia:

Pero cuando lo ejecuto, los tres punteros se comportan de la misma.

./testptr 
temp1:0x7fff3a85f220, temp2:0x7fff3a85f220, temp3:0x7fff3a85f220 
0 = 1, 1, 1 
1 = 2, 2, 2 

sé que buf == &buf[0], pero ¿por qué &buf == &buf[0]? ¿No debería &buf ser char**?

+1

'& buf' es en realidad un' char (*) [512] '(un puntero a una matriz de 512 elementos' char'). No son lo mismo. –

+0

Cambió su código entre capturar la salida del compilador y pegar el código en la pregunta. El problema está en la línea 9 ahora. –

+0

Lo siento, tiene razón, acaba de agregar una nueva línea – austinmarton

Respuesta

3

Todos los punteros se comportan de la misma, ya que declaró todos ellos para ser char*. C está tipado estáticamente por lo que el tipo está ligado a la variable y no al valor.

Ahora que se explica la parte del comportamiento, solo tenemos que averiguar por qué tienen realmente el mismo valor (según% p printf). Bueno, esto es solo un artefacto de punteros implementados como una dirección de memoria por GCC (los desplazamientos y el tamaño que hacen que un * sea diferente de un ** son manejados por el sistema de tipo/compilador detrás de las escenas).Tenga en cuenta que, como cualquiera de las cosas más sospechosas que emiten advertencias, es probable que sea un comportamiento indefinido o, al menos, una mala práctica :)

2

Las matrices no son punteros, aunque se pueden usar de la misma manera. Has encontrado un aspecto en el que la matriz y la semántica del puntero difieren.

+0

Descubrí esto cuando accidentalmente pasé '& buf' en lugar de' buf' como el segundo argumento de tipo 'void *' para la función [recv] (http://linux.die.net/man/2/recv) . ¿Es posible que esto pueda causar un problema aunque mi ejemplo anterior no lo ilustre? – austinmarton

+0

@austinmarton: Prefiero equivocarme del lado de la paranoia cuando se trata de las advertencias del compilador de C – hugomg

+0

@missingno: Llamada justa. En mi aplicación original, el error se pasó como un puntero de vacío por lo que no se generó ninguna advertencia. – austinmarton

1

Puede resolverlo desde el álgebra de los operadores * y &.

  • sabemos que buf es la dirección del elemento de orden 0 de la matriz buf

  • sabemos que &buf[0] es también la dirección del elemento de orden 0

  • por definición buf[0] es equivalente a *(buf+0)

  • y &(*(a)) es equivalente a a.

Por lo tanto, se convierte en &buf[0]&(*(buf+0)) que es buf.

actualización

Aquí, vamos a sentar a cabo como una prueba.

  1. &buf[0] Given.
  2. &(buf[0]) por reglas de prioridad C con() 's
  3. &((*(buf+0))) porque buf[0] == *(buf+0).
  4. &(*(buf+0)) eliminando parens extraños
  5. buf QED
+3

Estoy de acuerdo con lo que dices ('buf == & buf [0]'), pero eso no es exactamente lo que estoy preguntando ('& buf == buf'?). – austinmarton

+0

@austinmarton, sigue los pasos: son una prueba de que, sí, '& buf' es equivalente a' buf'. –

+1

@Charlie: No, la prueba dice que '& buf [0]' es equivalente a 'buf', no que' & buf' es equivalente a 'buf', que era lo que preguntaba la pregunta. – icktoofay

1

Si piensa qué código realmente está generando el compilador cuando procesa una matriz, se vuelve más clara. El nombre buf hace referencia a la dirección del primer elemento (cero) de la matriz (espacio contiguo para contener caracteres). Si observa el objeto en la entrada de la tabla de símbolos para "buf", encontrará la dirección de ese primer elemento. Cuando hace referencia, por ejemplo, buf [0], el compilador genera la dirección de buf, más cero veces el tamaño de un char. Esto pasa a ser lo mismo que la dirección de buf en sí.

Cuestiones relacionadas