มาโคร stdarg
va_list, va_start, va_arg
มาโคร stdarg เป็นบทเรียน C Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C Academy มีบทเรียนทั้งหมด 4 บทเรียน
ฟังก์ชันแปรผันคืออะไร
ฟังก์ชันแปรผันรับอาร์กิวเมนต์จำนวนไม่แน่นอน คุณเคยใช้ฟังก์ชันลักษณะนี้แล้วหนึ่งตัว นั่นคือ printf สามารถรับค่าได้กี่ค่าก็ได้
C ช่วยให้คุณเขียนฟังก์ชันของตนเองได้โดยใช้มาโครใน <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;
}จุดไข่ปลา
คุณประกาศฟังก์ชันแปรผันด้วย ... (จุดไข่ปลา) เป็นพารามิเตอร์ตัวสุดท้าย
ต้องมีพารามิเตอร์ที่มีชื่ออย่างน้อยหนึ่งตัวอยู่ก่อนหน้า เพื่อให้ฟังก์ชันทราบว่าส่วนที่มีจำนวนแปรผันเริ่มต้นที่ใด
#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
หากต้องการอ่านอาร์กิวเมนต์แปรผัน คุณต้องใช้ #include <stdarg.h>
ไฟล์นี้กำหนดชนิด va_list และมาโคร va_start va_arg และ 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 และ va_start
ประกาศตัวแปร va_list เพื่อติดตามตำแหน่งปัจจุบัน จากนั้นเรียก va_start(list, last) โดยส่งพารามิเตอร์ที่มีชื่อตัวสุดท้ายเข้าไป
การทำเช่นนี้จะชี้รายการไปยังอาร์กิวเมนต์แปรผันตัวแรก
#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: การอ่านค่า
va_arg(list, type) จะคืนอาร์กิวเมนต์ถัดไปและเลื่อนรายการไปข้างหน้า คุณต้องระบุชนิดที่จะอ่านให้ถูกต้องตรงกัน
การเรียกแต่ละครั้งจะเลื่อนไปข้างหน้าหนึ่งอาร์กิวเมนต์
#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: การเก็บกวาด
เรียก va_end(list) เสมอเมื่ออ่านเสร็จแล้ว ฟังก์ชันนี้จะดำเนินการเก็บกวาดตามที่แพลตฟอร์มต้องการ
หากลืมเรียกใช้ อาจทำให้เกิดพฤติกรรมที่ไม่กำหนดบนระบบบางระบบ
#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;
}การทราบจำนวนอาร์กิวเมนต์
มาโครไม่สามารถบอกคุณได้ว่ามีการส่งอาร์กิวเมนต์มา กี่ตัว คุณต้องระบุข้อมูลนี้ด้วยตนเอง
วิธีที่ใช้กันทั่วไปคือเพิ่มพารามิเตอร์จำนวนไว้ด้านหน้า ดังตัวอย่าง 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;
}การใช้ค่าเครื่องหมายสิ้นสุด
อีกวิธีหนึ่งในการระบุจุดสิ้นสุดคือใช้ เครื่องหมายสิ้นสุด ซึ่งเป็นค่าพิเศษที่ใช้ปิดรายการและผู้เรียกต้องใส่เข้ามา เช่น -1 หรือ NULL
วนซ้ำไปจนกว่าจะอ่านพบค่าเครื่องหมายสิ้นสุด
#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;
}การเลื่อนระดับอาร์กิวเมนต์เริ่มต้น
อาร์กิวเมนต์แบบแปรผันจะผ่าน การเลื่อนระดับเริ่มต้น: char และ short จะกลายเป็น int ส่วน float จะกลายเป็น double
ดังนั้นให้อ่านจำนวนเต็มขนาดเล็กเป็น int และอ่านค่าทศนิยมเป็น double ด้วย va_arg เสมอ
#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
หากต้องวนอ่านอาร์กิวเมนต์สองรอบ ให้ใช้ va_copy(dest, src) เพื่อทำสำเนารายการก่อนอ่าน
คุณไม่สามารถนำ va_list กลับมาใช้ซ้ำหลังจากเรียก va_end ได้ หากไม่เริ่มต้นใหม่ด้วย 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;
}การคำนวณค่าเฉลี่ย
เมื่อนำรูปแบบการระบุจำนวนมารวมกับการอ่านค่าทศนิยม เราจะสามารถหาค่าเฉลี่ยของรายการตัวเลขที่ส่งมาแบบแปรผันได้
#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;
}ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจเกี่ยวกับมาโคร stdarg ของคุณ
สรุปทบทวน
คุณได้เรียนรู้กลไกอาร์กิวเมนต์แบบแปรผัน:
- ประกาศด้วย
...หลังพารามิเตอร์ที่มีชื่ออย่างน้อยหนึ่งตัว va_start(list, last)ใช้เริ่มต้น,va_arg(list, type)ใช้อ่าน และva_end(list)ใช้เก็บกวาด- มาโครไม่ทราบจำนวนอาร์กิวเมนต์ — ให้ใช้พารามิเตอร์จำนวนหรือเครื่องหมายสิ้นสุด
- ระวังการเลื่อนระดับเริ่มต้น: อ่านจำนวนเต็มขนาดเล็กเป็น
intและค่าทศนิยมเป็นdouble
คำถามที่พบบ่อย
บทเรียน “มาโคร stdarg” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “มาโคร stdarg” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “มาโคร stdarg”
va_list, va_start, va_arg คุณปฏิบัติ C Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน C Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “มาโคร stdarg” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน C Academy นี้ได้ไหม
ได้ บทเรียน C Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ