Hvorfor returnerer denne funksjonen riktig lengde på en streng? (Inkrementere en tegnpeker)

 C Programming >> C C# Program >  >> Tags >> String
Hvorfor returnerer denne funksjonen riktig lengde på en streng? (Inkrementere en tegnpeker)

Verdien til s++ er den opprinnelige verdien av s , før inkrement, skjer inkrementet på et uspesifisert tidspunkt før neste sekvenspunkt.

Derfor *s++ og *(s++) er ekvivalente:de refererer begge til den opprinnelige verdien av s . Et annet ekvivalent uttrykk er *(0, s++) og ikke for sarte sjeler, slik er denne:0[s++]

Vær imidlertid oppmerksom på at funksjonen din bør bruke typen size_t for i og dens returtype:

size_t str_len(const char *s) {
    size_t i = 0;
    while (*s++) {
        i++;
    }
    /* s points after the null terminator */
    return i;
}

Her er en potensielt mer effektiv versjon med ett enkelt trinn per sløyfe:

size_t str_len(const char *s) {
    const char *s0 = s;
    while (*s++) {
        /* nothing */
    }
    return s - 1 - s0;
}

For de som lurer på de rare uttrykkene i andre avsnitt:

  • 0, s++ er en forekomst av kommaoperatoren , som vurderer dens venstre del, deretter dens høyre del som utgjør dens verdi. derav (0, s++) tilsvarer (s++) .

  • 0[s++] tilsvarer (s++)[0] og *(0 + s++) eller *(s++ + 0) som forenkles som *(s++) . Transponering av pekeren og indeksuttrykkene i [] uttrykk er ikke veldig vanlig eller spesielt nyttig, men samsvarer med C-standarden.


I det eksemplet, s peker på 'a' i "a" . Deretter økes den og i er også økt. Nå s pek på nullterminatoren, og i er 1 . Så i neste løp gjennom løkken, *(s++) er '\0' (som er 0 ), så løkken slutter, og gjeldende verdi på i (det er 1 ) returneres.

Vanligvis kjører løkken én gang for hvert tegn i strengen, og stopper deretter ved nullterminatoren, så det er slik den teller tegnene.


Det gir perfekt mening:

int str_len(const char* s) {
    int i = 0;
    while(*(s++)) { //<-- increments the pointer to char till the end of the string
                    //till it finds '\0', that is, if s = "a" then s is 'a'
                    // followed by '\0' so it increments one time
        i++; //counts the number of times the pointer moves forward
    }
    return i;
}

Det er nettopp derfor pekeren økes og ikke tegnet, la oss si at du har (*s)++ , i dette tilfellet vil tegnet økes og ikke pekeren. Derereferansen betyr at du nå arbeider med verdien referert av pekeren, ikke pekeren i seg selv.

Siden begge operatorene har samme forrang, men assosiativitet fra høyre til venstre, kan du til og med bruke *s++ uten parentes for å øke pekeren.