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, ava_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 jakodouble.
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.