0Pricing
C Academy · บทเรียน

มาโคร 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. มาโคร stdarg
  2. การเขียนฟังก์ชันแบบ printf
  3. ข้อควรระวังด้านความปลอดภัยของชนิด
  4. ตัวอย่างการใช้งานจริง
← กลับไปที่ C Academy