Właśnie zacząłem uczyć się C i kiedy robiłem jeden przykład dotyczący przekazywania wskaźnika do wskaźnika jako parametru funkcji, znalazłem problem.
Oto mój przykładowy kod:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int* allocateIntArray(int* ptr, int size){
if (ptr != NULL){
for (int i = 0; i < size; i++){
ptr[i] = i;
}
}
return ptr;
}
void increasePointer(int** ptr){
if (ptr != NULL){
*ptr += 1; /* <----------------------------- This is line 16 */
}
}
int main()
{
int* p1 = (int*)malloc(sizeof(int)* 10);
allocateIntArray(p1, 10);
for (int i = 0; i < 10; i++){
printf("%d\n", p1[i]);
}
increasePointer(&p1);
printf("%d\n", *p1);
p1--;
free(p1);
fgets(string, sizeof(string), stdin);
return 0;
}
Problem pojawia się w linii 16, kiedy modyfikuję *ptr+=1
do *ptr++
. Oczekiwanym wynikiem powinna być cała tablica i liczba 1, ale kiedy używam *ptr++
wyniku, to 0.
Czy jest jakaś różnica między +=1
a ++
? Myślałem, że obaj są tacy sami.
c
pointers
post-increment
huy nguyen
źródło
źródło
string
.allocateIntArray
to zła nazwa, ponieważ wydaje cimalloc
się tablica z funkcji, ale tak nie jest. ProponujęfillIntArray
zamiast tego. 2) Nie używasz zwracanej wartościallocateIntArray
. Proponuję zmienić typ zwrotu navoid
. 3) nie powinnaif (ptr != NULL)
w funkcjęincreasePointer
byćif (*ptr != NULL)
? 4) Wrzuceniemalloc
jest zbędne. Zobacz komentarz Sourav powyżej. 5) To:for (int i = 0; i < 10; i++){ printf("%d\n", p1[i]); }
iprintf("%d\n", *p1); p1--;
musi być zawarte wif(p1 != NULL)
. 6)string.h
jest nieużywany.p+=1
jest jak++p
, a nie jakp++
Odpowiedzi:
Różnica wynika z pierwszeństwa operatorów.
Operator post-inkrementacji
++
ma wyższy priorytet niż operator wyłuskiwania*
. Więc*ptr++
jest równoważne*(ptr++)
. Innymi słowy, przyrost postu modyfikuje wskaźnik, a nie to, na co wskazuje.Operator przypisania
+=
ma niższy priorytet niż operator wyłuskiwania*
, więc*ptr+=1
jest równoważny(*ptr)+=1
. Innymi słowy, operator przypisania modyfikuje wartość wskazywaną przez wskaźnik i nie zmienia samego wskaźnika.źródło
*p++
i*++p
. Pierwszeństwo operatorów tego drugiego jest jasne, następuje pierwszy z pierwszych.Kolejność pierwszeństwa dla 3 operatorów, których dotyczy Twoje pytanie, jest następująca:
post-inkrementacja
++
> dereference*
> przypisanie+=
Możesz sprawdzić tę stronę, aby uzyskać więcej informacji na ten temat.
Krótko mówiąc, aby wyrazić to przypisanie
*ptr+=1
za pomocą operatora post-inkrementacji, musisz dodać nawiasy do operatora wyłuskiwania, aby nadać tej operacji pierwszeństwo przed++
jak w tym(*ptr)++
źródło
Zastosujmy nawiasy, aby pokazać kolejność operacji
Zróbmy to jeszcze raz
I znowu z
*ptr += 1
zwiększamy wartość zmiennej, na którą wskazuje nasz wskaźnik .*ptr++
zwiększamy wskaźnik po wykonaniu całej instrukcji (linii kodu) i zwracamy odniesienie do zmiennej, na którą wskazuje nasz wskaźnik .Ta ostatnia pozwala na:
Jest to typowa metoda kopiowania
src
tablicy do innejdest
tablicy.źródło
Bardzo dobre pytanie.
W K&R „języku programowania C” „5.1 Wskaźniki i adresy” możemy uzyskać odpowiedź na to pytanie.
„Operatory jednoargumentowe * i & wiążą ściślej niż operatory arytmetyczne”
„Operatory jednoargumentowe, takie jak * i ++, kojarzą się od prawej do lewej ”.
// Działa jak * (ptr ++).
Prawidłowy sposób to:
źródło
* ptr + = 1: przyrost danych, na które wskazuje ptr. * ptr ++: Wskaźnik przyrostowy, który wskazuje następną lokalizację w pamięci zamiast danych, na które wskazuje wskaźnik.
źródło