0Pricing
C Academy · Lekcja

Makra stdarg

va_list, va_start, va_arg

Makra stdarg to bezpłatna lekcja C Academy na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C Academy zawiera 4 lekcji w sumie.

Czym są funkcje wariadyczne?

Funkcja wariadyczna przyjmuje zmienną liczbę argumentów. Używali już Państwo takiej funkcji: printf może przyjmować dowolną liczbę wartości.

W języku C można tworzyć własne funkcje tego typu za pomocą makr z <stdarg.h>.

#include <stdio.h>

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

Wielokropek

Funkcję wariadyczną deklaruje się, umieszczając ... (wielokropek) jako ostatni parametr.

Przed nim musi znajdować się co najmniej jeden parametr nazwany, aby funkcja wiedziała, gdzie zaczyna się część zmienna.

#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;
}

Dołączanie stdarg.h

Aby odczytywać zmienne argumenty, należy użyć #include <stdarg.h>.

Plik ten definiuje typ va_list oraz makra va_start, va_arg i 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 i va_start

Należy zadeklarować zmienną typu va_list, która będzie śledzić bieżącą pozycję. Następnie należy wywołać va_start(list, last), przekazując ostatni nazwany parametr.

Spowoduje to ustawienie listy na pierwszym zmiennym argumencie.

#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: odczytywanie wartości

va_arg(list, type) zwraca następny argument i przesuwa listę. Należy podać dokładny typ, który ma zostać odczytany.

Każde wywołanie przesuwa pozycję o jeden argument do przodu.

#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: sprzątanie

Zawsze należy wywołać va_end(list) po zakończeniu odczytywania argumentów. Funkcja wykonuje wszelkie czynności porządkowe wymagane przez platformę.

Pominięcie tego wywołania prowadzi do niezdefiniowanego działania w niektórych systemach.

#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;
}

Ustalanie liczby argumentów

Makra nie potrafią określić, ile argumentów zostało przekazanych. Musi to zostać przekazane osobno.

Popularnym rozwiązaniem jest parametr z liczbą umieszczony na początku, jak w 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;
}

Używanie wartości wartownika

Innym sposobem oznaczenia końca jest wartownik: specjalna wartość kończąca, którą wywołujący musi przekazać, na przykład -1 lub NULL.

Należy wykonywać pętlę do momentu odczytania wartości wartownika.

#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;
}

Domyślne promocje argumentów

Argumenty wariadyczne podlegają domyślnym promocjom: char i short są konwertowane do int, a float do double.

Dlatego za pomocą va_arg małe liczby całkowite należy zawsze odczytywać jako int, a liczby zmiennoprzecinkowe jako double.

#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;
}

Kopiowanie va_list

Jeśli argumenty trzeba przejść dwukrotnie, przed rozpoczęciem odczytu należy użyć va_copy(dest, src), aby skopiować listę.

Nie można ponownie użyć va_list po va_end bez ponownego rozpoczęcia za pomocą va_start.

#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;
}

Obliczanie średniej

Łącząc schemat z licznikiem z odczytywaniem wartości zmiennoprzecinkowych, można obliczyć średnią z listy liczb przekazanych wariadycznie.

#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;
}

Szybkie sprawdzenie

Sprawdź swoją wiedzę na temat makr stdarg.

Podsumowanie

Poznałeś mechanizm argumentów wariadycznych:

  • Deklaruj je za pomocą ... po co najmniej jednym nazwanym parametrze.
  • va_start(list, last) rozpoczyna pracę, va_arg(list, type) odczytuje argumenty, a va_end(list) wykonuje sprzątanie.
  • Makra nie znają liczby argumentów — użyj parametru z liczbą albo wartownika.
  • Pamiętaj o domyślnych promocjach: małe liczby całkowite odczytuj jako int, a liczby zmiennoprzecinkowe jako double.

Często zadawane pytania

Czy lekcja „Makra stdarg” jest bezpłatna?

Tak — pełny tekst „Makra stdarg” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C Academy, przejdź na CoddyKit PRO. Kurs C Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Makra stdarg”?

va_list, va_start, va_arg Ćwiczysz C Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć C Academy?

Nie wymagamy żadnego doświadczenia. C Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.

Ile czasu zajmuje lekcja „Makra stdarg”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji C Academy?

Tak. Każda lekcja C Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Makra stdarg
  2. Pisanie funkcji podobnych do printf
  3. Problemy z bezpieczeństwem typów
  4. Praktyczne przykłady
← Powrót do C Academy