Qual è la differenza tra * p e (* p) nella funzione?

Sono nuovo nella programmazione e nell’apprendimento dei puntatori nell’array in C. Dai un’occhiata ai programmi di seguito.

1 ° programma

#include int fun(); int main() { int num[3][3]={21,325,524,52,0,6514,61,33,85}; fun(num); printf("%d",*(*(num+1)+1)); *(*(num+1)+1)=0; printf("%d",*(*(num+1)+1)); return 0; } int fun(int **p) { *(*(p+1)+1)=2135; return 0; } 

2 ° programma

  #include int fun(); int main() { int num[3][3]={21,325,524,52,0,6514,61,33,85}; fun(num); printf("%d",*(*(num+1)+1)); *(*(num+1)+1)=0; printf("%d",*(*(num+1)+1)); return 0; } int fun(int *p) { *((p+1)+1)=2135; return 0; } 

3 ° programma

  #include int fun(); int main() { int num[3][3]={21,325,524,52,0,6514,61,33,85}; fun(num); printf("%d",*(*(num+1)+1)); *(*(num+1)+1)=0; printf("%d",*(*(num+1)+1)); return 0; } int fun(int (*p)[3]) { *(*(p+1)+1)=2135; return 0; } 
  1. Nel primo programma **p è usato nella funzione fun() che penso dovrebbe essere corretta e in quella funzione ho scritto *(*(p+1)+1) per cambiare il primo elemento del primo array. Ma alla compilazione di questo programma viene visualizzato l’ error: invalid type argument of unary '*' (have 'int') . Per quanto ne so num è un puntatore all’array e sta tenendo l’indirizzo di num[1] che sta di nuovo tenendo l’indirizzo di num[1][0] .
  2. Alla compilazione del secondo programma il compilatore non mostra alcun errore. E *((p+1)+1)=0 sta cambiando il valore del 2 ° elemento del primo array. Perché sta cambiando il valore del 2 ° elemento dell’array zeroth e non il valore del primo elemento del primo array? e come? Dovrebbe essere *(*(p+1)+1)=0 .
  3. Nel terzo programma il compler non mostra alcun errore e sta mostrando il risultato corretto. Come?. Cosa significa *(p)[3] ?

Avevo cercato su questo ma non ho trovato il risultato soddisfacente.

Penso che tu stia chiedendo: qual è la differenza tra

 int fun(int *p) 

e

 int fun(int (*p)[3]) 

Il primo si aspetta un puntatore a un int . Il secondo si aspetta un puntatore a un array di 3 int s.

Sei in grado di chiamare entrambe queste funzioni usando num dato che hai dichiarato la funzione come

 int fun(); 

Se si dichiarano le funzioni come sono definite, si otterrà errore / avviso del compilatore per la prima versione.

Ecco una versione aggiornata del tuo codice e l’avviso del compilatore risultante, utilizzando gcc e flag del compilatore -Wall .

 #include  int fun(int *p); int main() { int num[3][3]={21,325,524,52,0,6514,61,33,85}; fun(num); return 0; } int fun(int *p) { *(p+0)=2135; return 0; } 
 test.c: In function 'main': test.c:7:4: warning: missing braces around initializer [-Wmissing-braces] test.c:7:4: warning: (near initialization for 'num[0]') [-Wmissing-braces] test.c:8:4: warning: passing argument 1 of 'fun' from incompatible pointer type [enabled by default] test.c:3:5: note: expected 'int *' but argument is of type 'int (*)[3]' 

Tutti i tuoi programmi sono mal formati. Il compilatore deve produrre messaggi di avviso o di errore e l’output di qualsiasi eseguibile prodotto non ha senso.

Sono mal formati perché int[3][3] non è compatibile con int ** , né con int * , né con int *[3] .

Per passare int[3][3] a una funzione, la funzione deve accettare int (*)[3] e nient’altro (beh, ad eccezione di void * ).

Questo perché gli array possono essere convertiti in un puntatore al primo elemento dell’array. (Nella syntax C, num può essere usato per significare &num[0] ).

In C, ci sono solo array unidimensionali; una matrice di tipo int[3][3] è considerata una matrice di 3 elementi, ognuno dei quali è un array di 3 ints.

Quindi un puntatore al primo elemento di num è un puntatore a un array di 3 pollici, che è scritto come int (*p)[3] . Potresti scrivere:

 int (*p)[3] = &num[0]; 

o la scorciatoia per la stessa cosa:

 int (*p)[3] = num; 

NB. Scrivi continuamente *(*(num+1)+1)) che è difficile da leggere. Invece di questo, num[1][1] sembra molto più chiaro.

In C, x[y] è sempre esattamente equivalente a *(x+y) .