C Academy · Oppitunti

stdarg-makrot

va_list, va_start, va_arg.

Oppitunti 1/413 vaihetta

stdarg-makrot on ilmainen C Academy-oppitunti CoddyKitissä. Tämä on oppitunti 1/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu C Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. C Academy-kurssilla on yhteensä 4 oppituntia.

Mitä variadiset funktiot ovat?

Variadinen funktio hyväksyy vaihtelevan määrän argumentteja. Olette jo käyttäneet sellaista: printf voi ottaa minkä tahansa määrän arvoja.

C-kielessä voitte kirjoittaa omia variadisia funktioita makrojen <stdarg.h> avulla.

#include <stdio.h>

int main(void) {
    printf("%d %d %d\n", 1, 2, 3);
    printf("%s\n", "any count of args");
    return 0;
}

Kolme pistettä

Variadinen funktio määritellään käyttämällä viimeisenä parametrina kolmea pistettä ....

Sitä ennen on oltava vähintään yksi nimetty parametri, jotta funktio tietää, mistä muuttuva osa alkaa.

#include <stdio.h>
#include <stdarg.h>

void demo(int count, ...) {
    printf("This function takes %d extra args\n", count);
}

int main(void) {
    demo(3, 10, 20, 30);
    return 0;
}

stdarg.h:n sisällyttäminen

Muuttuvien argumenttien lukemista varten tarvitsette direktiivin #include <stdarg.h>.

Se määrittelee tyypin va_list sekä makrot va_start, va_arg ja va_end.

#include <stdio.h>
#include <stdarg.h>

void show(int n, ...) {
    va_list args;
    va_start(args, n);
    va_end(args);
    printf("set up and cleaned up\n");
}

int main(void) {
    show(2, 5, 6);
    return 0;
}

va_list ja va_start

Ilmoittakaa va_list-muuttuja seuraamaan nykyistä sijaintia. Kutsukaa sitten va_start(list, last) ja välittäkää sille viimeinen nimetty parametri.

Tämä kohdistaa luettelon ensimmäiseen muuttuvaan argumenttiin.

#include <stdio.h>
#include <stdarg.h>

void first(int count, ...) {
    va_list args;
    va_start(args, count);
    int value = va_arg(args, int);
    printf("first variadic arg = %d\n", value);
    va_end(args);
}

int main(void) {
    first(1, 99);
    return 0;
}

va_arg: arvojen lukeminen

va_arg(list, type) palauttaa seuraavan argumentin ja siirtää luetteloa eteenpäin. Teidän on ilmoitettava sille luettavan arvon täsmällinen tyyppi.

Jokainen kutsu siirtyy yhden argumentin eteenpäin.

#include <stdio.h>
#include <stdarg.h>

void three(int n, ...) {
    va_list args;
    va_start(args, n);
    int a = va_arg(args, int);
    int b = va_arg(args, int);
    int c = va_arg(args, int);
    printf("%d %d %d\n", a, b, c);
    va_end(args);
}

int main(void) {
    three(3, 7, 8, 9);
    return 0;
}

va_end: siivous

Kutsukaa aina va_end(list), kun olette lopettaneet lukemisen. Se suorittaa alustan tarvitsemat siivoustoimet.

Sen unohtaminen johtaa joissakin järjestelmissä määrittelemättömään toimintaan.

#include <stdio.h>
#include <stdarg.h>

int add_two(int dummy, ...) {
    va_list args;
    va_start(args, dummy);
    int sum = va_arg(args, int) + va_arg(args, int);
    va_end(args);
    return sum;
}

int main(void) {
    printf("%d\n", add_two(0, 4, 6));
    return 0;
}

Argumenttien määrän tietäminen

Makrot eivät voi tietää, kuinka monta argumenttia välitettiin. Teidän on välitettävä tämä tieto itse.

Yleinen tapa on käyttää alussa olevaa lukumääräparametria, kuten kutsussa sum(3, a, b, c).

#include <stdio.h>
#include <stdarg.h>

int sum(int count, ...) {
    va_list args;
    va_start(args, count);
    int total = 0;
    for (int i = 0; i < count; i++)
        total += va_arg(args, int);
    va_end(args);
    return total;
}

int main(void) {
    printf("%d\n", sum(4, 1, 2, 3, 4));
    return 0;
}

Sentineliarvon käyttäminen

Toinen tapa merkitä loppu on sentineli: erityinen lopetusarvo, joka kutsujan on annettava, kuten -1 tai NULL.

Toistakaa silmukkaa, kunnes luette sentinelin.

#include <stdio.h>
#include <stdarg.h>

int sum_until_neg(int first, ...) {
    va_list args;
    va_start(args, first);
    int total = first, v;
    while ((v = va_arg(args, int)) != -1)
        total += v;
    va_end(args);
    return total;
}

int main(void) {
    printf("%d\n", sum_until_neg(10, 20, 30, -1));
    return 0;
}

Oletusargumenttipromootiot

Vaihtelevat argumentit käyvät läpi oletuspromootiot: char ja short muuttuvat tyypiksi int, ja float muuttuu tyypiksi double.

Lukekaa siis pienet kokonaisluvut aina tyyppinä int ja liukuluvut tyyppinä double käyttämällä va_arg-makroa.

#include <stdio.h>
#include <stdarg.h>

void show_double(int n, ...) {
    va_list args;
    va_start(args, n);
    double d = va_arg(args, double);
    printf("%.2f\n", d);
    va_end(args);
}

int main(void) {
    show_double(1, 3.5f);
    return 0;
}

va_list-tyypin kopioiminen

Jos tarvitsette argumenttien läpikäyntiä kahdesti, käyttäkää va_copy(dest, src) -kutsua listan kopioimiseen ennen lukemista.

Ette voi käyttää va_list-tyyppistä listaa uudelleen va_end-kutsun jälkeen ilman, että aloitatte sen uudelleen va_start-kutsulla.

#include <stdio.h>
#include <stdarg.h>

void twice(int n, ...) {
    va_list a, b;
    va_start(a, n);
    va_copy(b, a);
    printf("%d %d\n", va_arg(a, int), va_arg(b, int));
    va_end(a);
    va_end(b);
}

int main(void) {
    twice(1, 42);
    return 0;
}

Keskiarvon laskeminen

Yhdistämällä lukumäärämallin liukulukujen lukemiseen voimme laskea vaihtelevina argumentteina välitettyjen lukujen keskiarvon.

#include <stdio.h>
#include <stdarg.h>

double average(int count, ...) {
    va_list args;
    va_start(args, count);
    double sum = 0;
    for (int i = 0; i < count; i++)
        sum += va_arg(args, double);
    va_end(args);
    return sum / count;
}

int main(void) {
    printf("%.2f\n", average(3, 2.0, 4.0, 6.0));
    return 0;
}

Pikatarkistus

Testatkaa, miten hyvin ymmärrätte stdarg-makroja.

Kertaus

Opitte vaihtelevien argumenttien mekanismin:

  • Ilmoittakaa funktio vähintään yhden nimetyn parametrin jälkeen merkinnällä ....
  • va_start(list, last) aloittaa käsittelyn, va_arg(list, type) lukee arvon ja va_end(list) suorittaa siivouksen.
  • Makrot eivät tiedä argumenttien määrää — käyttäkää lukumääräparametria tai sentineliä.
  • Huomioikaa oletuspromootiot: lukekaa pienet kokonaisluvut tyyppinä int ja liukuluvut tyyppinä double.
Aloita maksutta

Opi C tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
39
Oppitunnit
144

Usein kysytyt kysymykset

Onko oppitunti ”stdarg-makrot” ilmainen?

Kyllä – oppitunnin ”stdarg-makrot” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko C Academy-kurssin, päivitä CoddyKit PROhon. C Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”stdarg-makrot”?

va_list, va_start, va_arg. Harjoittelet C Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni C Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin C Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 1/4.

Kuinka kauan ”stdarg-makrot”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä C Academy-oppitunnilla?

Kyllä. Jokainen C Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. stdarg-makrot
  2. printf-tyyppisten funktioiden kirjoittaminen
  3. Tyyppiturvallisuuden ongelmat
  4. Käytännön esimerkkejä
← Takaisin: C Academy