O valor de s++
é o valor original de s
, antes do incremento, o incremento ocorre em um tempo não especificado antes do próximo ponto de sequência.
Daí *s++
e *(s++)
são equivalentes: ambos desreferenciam o valor original de s
. Outra expressão equivalente é *(0, s++)
e, não para os fracos de coração, é esta:0[s++]
Observe, no entanto, que sua função deve usar type size_t
for i
e seu tipo de retorno:
size_t str_len(const char *s) {
size_t i = 0;
while (*s++) {
i++;
}
/* s points after the null terminator */
return i;
}
Aqui está uma versão potencialmente mais eficiente com um único incremento por loop:
size_t str_len(const char *s) {
const char *s0 = s;
while (*s++) {
/* nothing */
}
return s - 1 - s0;
}
Para aqueles que se perguntam sobre as expressões estranhas no segundo parágrafo:
0, s++
é uma instância do operador de vírgula ,
que avalia sua parte esquerda e depois a parte direita, que constitui seu valor. portanto, (0, s++)
é equivalente a (s++)
.
0[s++]
é equivalente a (s++)[0]
e *(0 + s++)
ou *(s++ + 0)
que simplifica como *(s++)
. Transpor o ponteiro e as expressões de índice em []
expressões não é muito comum nem particularmente útil, mas está em conformidade com o padrão C.
, s++
coisas ruins e acontecerá:)
Nesse exemplo,
s
aponta para o'a'
in"a"
. Então é incrementado ei
também é incrementado. Agoras
aponte para o terminador nulo ei
é1
. Portanto, na próxima execução do loop,*(s++)
é'\0'
(is0
), então o loop termina e o valor atual dei
(that1
) é retornado.Geralmente, o loop é executado uma vez para cada caractere na string e, em seguida, para no terminador nulo, e é assim que conta os caracteres.
fonte
s
mantido antes de incrementar. O que você está descrevendo é o comportamento de++s
(que de fato subconta por um e invoca o UB se for passado uma string vazia).Faz todo o sentido:
É exatamente por isso que o ponteiro é incrementado e não o caractere, digamos que você tenha
(*s)++
, nesse caso, o caractere será incrementado e não o ponteiro. A desreferenciação significa que agora você está trabalhando com o valor referido pelo ponteiro, não o ponteiro em si.Como os dois operadores têm a mesma precedência, mas associatividade da direita para a esquerda, você pode até usar simplesmente
*s++
sem colchetes para aumentar o ponteiro.fonte
O operador pós-incremento aumenta o valor do operando em 1, mas o valor da expressão é o valor original do operando antes da operação de incremento.
Suponha que o argumento passado para
str_len()
é"a"
. Nostr_len()
, o ponteiros
está apontando para o primeiro caractere da string"a"
. Nowhile
loop:embora o
s
seja incrementado, mas o valor des
na expressão será o ponteiro para o caractere para o qual está apontando antes do incremento, que é o ponteiro para o primeiro caractere'a'
. Quando o ponteiros
é desreferenciado, ele fornece um caractere'a'
. Na próxima iteração, os
ponteiro estará apontando para o próximo caractere, que é o caractere nulo\0
. Quandos
for desreferenciado, ele dará0
e o loop será encerrado. Observe ques
agora apontará para um elemento além do caractere nulo da string"a"
.fonte