Речь идет о функции strcat
.
while (*p) p++;
а также
while (*++p) ;
обе работы, но
while (*p++) ;
не работает. Я думаю, что первая и третья должны быть одинаковыми, но это не так.
И то и другое
while (*p) p++;
а также
while (*++p) ;
будет продвигать p
чтобы указать на терминатор 0 в строке, тогда как
while (*p++) ;
будет продвигать p
чтобы указать один символ за 0 терминатором.
Чтобы понять, почему, предположим следующие символы в памяти:
Address 0x00 0x01 0x02 0x03 ------- ---- ---- ---- ---- 0x8000 'a' 'b' 'c' 0 0x8004 ...
Предположим, что p
начинается с адреса 0x8000. Вот как выглядит первый цикл:
1. *p = 'a' 2. p = 0x8001 3. *p = 'b' 4. p = 0x8002 5. *p = 'c' 6. p = 0x8003 7. *p = 0 8. end loop
Вот как выглядит второй цикл:
1. p = 0x8001 2. *p = 'b' 3. p = 0x8002 4. *p = 'c' 5. p = 0x8003 6. *p = 0 7. end loop
И вот последний:
1. *p = 'a' 2. p = 0x8001 3. *p = 'b' 4. p = 0x8002 5. *p = 'c' 6. p = 0x8003 7. *p = 0; 8. p = 0x8004 9. end loop
В последней версии оценка *p++
продвигает указатель, даже если значение *p
равно 0.
Предположим, что p
– строка.
while (*p) p++; /* (1) */ while (*++p) ; /* (2) */ while (*p++) ; /* (3) */
p
– пустая строка. *p
является символом '\0'
, p
увеличивается. // move p forward as long as it points to a non-0 character, // leave it pointing to a 0 character. while (*p) p++; // move p forward until it points to a 0 character, skipping the first // character before you start while (*++p); // move p forward until it points one past a 0 character while (*p++);
Поэтому, учитывая, что (1) «работает»: (2) также работает, если p
первоначально указывает на непустую строку. (3) не работает вообще, потому что p
заканчивается, указывая на другое место.
*++p
увеличивает p
а затем оценивает то, на что указывает p
. *p++
оценивает то, что изначально указывает на p
, но также увеличивает p
. Следовательно, (2) и (3) различны.
(1) и (3) различны, потому что (3) выполняет p++
, тогда он решает, остановить ли. (1) сначала смотрит на *p
чтобы решить, стоит ли останавливаться, а если не останавливать, он выполняет p++
.
* ++ p означает увеличение этой переменной, а затем ее использование
* p ++ означает использование переменной, затем увеличивайте ее