Допустим,
int *p;
int a = 100;
p = &a;
Что на самом деле будет делать следующий код и как?
p++;
++p;
++*p;
++(*p);
++*(p);
*p++;
(*p)++;
*(p)++;
*++p;
*(++p);
Я знаю, что это немного запутанно с точки зрения кодирования, но я хочу знать, что на самом деле произойдет, когда мы будем кодировать таким образом.
Примечание: Предположим, что адрес a=5120300
хранится в указателе p
, адрес которого равен 3560200
. Теперь, каково будет значение p & a
после выполнения каждого оператора?
printf
напечатает указатель с% pОтветы:
Во-первых, оператор ++ имеет приоритет над оператором *, а операторы () имеют приоритет над всем остальным.
Во-вторых, оператор числа ++ совпадает с оператором числа ++, если вы не назначаете его чему-либо. Разница в том, что число ++ возвращает число, а затем увеличивает число, а ++ число сначала увеличивает, а затем возвращает его.
В-третьих, увеличивая значение указателя, вы увеличиваете его на размер его содержимого, то есть увеличиваете его, как если бы вы выполняли итерацию в массиве.
Итак, подведем итог:
ptr++; // Pointer moves to the next int position (as if it was an array) ++ptr; // Pointer moves to the next int position (as if it was an array) ++*ptr; // The value of ptr is incremented ++(*ptr); // The value of ptr is incremented ++*(ptr); // The value of ptr is incremented *ptr++; // Pointer moves to the next int position (as if it was an array). But returns the old content (*ptr)++; // The value of ptr is incremented *(ptr)++; // Pointer moves to the next int position (as if it was an array). But returns the old content *++ptr; // Pointer moves to the next int position, and then get's accessed, with your code, segfault *(++ptr); // Pointer moves to the next int position, and then get's accessed, with your code, segfault
Поскольку здесь много случаев, я мог сделать какую-то ошибку, поправьте меня, если я ошибаюсь.
РЕДАКТИРОВАТЬ:
Итак, я ошибался, приоритет немного сложнее, чем то, что я написал, просмотрите его здесь: http://en.cppreference.com/w/cpp/language/operator_precedence
источник
проверил программу и результаты такие,
p++; // use it then move to next int position ++p; // move to next int and then use it ++*p; // increments the value by 1 then use it ++(*p); // increments the value by 1 then use it ++*(p); // increments the value by 1 then use it *p++; // use the value of p then moves to next position (*p)++; // use the value of p then increment the value *(p)++; // use the value of p then moves to next position *++p; // moves to the next int location then use that value *(++p); // moves to next location then use that value
источник
Ниже приводится пример различных предложений «просто распечатать». Я нашел это поучительным.
#include "stdio.h" int main() { static int x = 5; static int *p = &x; printf("(int) p => %d\n",(int) p); printf("(int) p++ => %d\n",(int) p++); x = 5; p = &x; printf("(int) ++p => %d\n",(int) ++p); x = 5; p = &x; printf("++*p => %d\n",++*p); x = 5; p = &x; printf("++(*p) => %d\n",++(*p)); x = 5; p = &x; printf("++*(p) => %d\n",++*(p)); x = 5; p = &x; printf("*p++ => %d\n",*p++); x = 5; p = &x; printf("(*p)++ => %d\n",(*p)++); x = 5; p = &x; printf("*(p)++ => %d\n",*(p)++); x = 5; p = &x; printf("*++p => %d\n",*++p); x = 5; p = &x; printf("*(++p) => %d\n",*(++p)); return 0; }
Он возвращается
(int) p => 256688152 (int) p++ => 256688152 (int) ++p => 256688156 ++*p => 6 ++(*p) => 6 ++*(p) => 6 *p++ => 5 (*p)++ => 5 *(p)++ => 5 *++p => 0 *(++p) => 0
Я привел адреса указателя к
int
s, чтобы их можно было легко сравнить.Я скомпилировал его с помощью GCC.
источник
Что касается вопроса «Как увеличить адрес указателя и значение указателя?» Я думаю, что
++(*p++);
это на самом деле хорошо определено и делает то, о чем вы просите, например:#include <stdio.h> int main() { int a = 100; int *p = &a; printf("%p\n",(void*)p); ++(*p++); printf("%p\n",(void*)p); printf("%d\n",a); return 0; }
Это не изменение одного и того же дважды перед точкой последовательности. Я не думаю, что это хороший стиль для большинства применений - на мой взгляд, он слишком загадочен.
источник
++*p++
успешно увеличивают и значение, и указатель (постфиксная++
привязка сильнее, чем разыменование*
, и это происходит до префикса++
из-за порядка). Скобки необходимы только тогда, когда вам нужно значение перед его увеличением(*p++)++
. Если вы выберете all-prefix, он++*++p
будет работать нормально и без круглых скобок (но увеличивайте значение, указанное после приращения указателя).Note: 1) Both ++ and * have same precedence(priority), so the associativity comes into picture. 2) in this case Associativity is from **Right-Left** important table to remember in case of pointers and arrays: operators precedence associativity 1) () , [] 1 left-right 2) * , identifier 2 right-left 3) <data type> 3 ---------- let me give an example, this might help; char **str; str = (char **)malloc(sizeof(char*)*2); // allocate mem for 2 char* str[0]=(char *)malloc(sizeof(char)*10); // allocate mem for 10 char str[1]=(char *)malloc(sizeof(char)*10); // allocate mem for 10 char strcpy(str[0],"abcd"); // assigning value strcpy(str[1],"efgh"); // assigning value while(*str) { cout<<*str<<endl; // printing the string *str++; // incrementing the address(pointer) // check above about the prcedence and associativity } free(str[0]); free(str[1]); free(str);
источник