การใช้งานเลขฐานสิบหกในภาษา C: พื้นฐานและตัวอย่างการประยุกต์แบบครบถ้วน

目次

1. บทนำ

ภาษา C เป็นภาษาการเขียนโปรแกรมที่ทรงพลังซึ่งนักพัฒนาใช้กันอย่างแพร่หลาย และมีวิธีการมากมายในการจัดการตัวเลขอย่างมีประสิทธิภาพ หนึ่งในนั้นคือ “เลขฐานสิบหก” ซึ่งถูกใช้บ่อยในงานที่เกี่ยวกับการจัดการบิตและหน่วยความจำ บทความนี้จะอธิบายตั้งแต่พื้นฐานไปจนถึงการประยุกต์ใช้เลขฐานสิบหกในภาษา C โดยอธิบายเป็นลำดับขั้นตอนเพื่อให้ผู้เริ่มต้นก็สามารถเข้าใจได้

2. วิธีการแสดงตัวเลข

ความแตกต่างระหว่างเลขฐานสิบ เลขฐานแปด และเลขฐานสิบหก

ในภาษา C สามารถแสดงตัวเลขได้ดังนี้:

  1. เลขฐานสิบ (Decimal)
    เป็นรูปแบบตัวเลขที่มนุษย์ใช้ในชีวิตประจำวัน เช่น 123 จะถูกตีความเป็นเลขฐานสิบ
  2. เลขฐานแปด (Octal)
    ถ้าวางเลข 0 ไว้หน้าตัวเลข จะถือว่าเป็นเลขฐานแปด เช่น 0123 หมายถึง “83” ในฐานสิบ
  3. เลขฐานสิบหก (Hexadecimal)
    ถ้าวาง 0x หรือ 0X ไว้หน้าตัวเลข จะตีความว่าเป็นเลขฐานสิบหก เช่น 0x123 หมายถึง “291” ในฐานสิบ

ข้อดีของเลขฐานสิบหก

เลขฐานสิบหกถูกใช้เป็นรูปแบบย่อของเลขฐานสอง โดย 1 หลักของเลขฐานสิบหกสามารถแทนค่าได้ 4 บิตของเลขฐานสอง ทำให้สะดวกมากสำหรับการทำงานระดับบิต นอกจากนี้ยังใช้บ่อยในการดีบักเพื่อตรวจสอบเนื้อหาหน่วยความจำ

3. พื้นฐานของเลขฐานสิบหก

โครงสร้างของเลขฐานสิบหก

เลขฐานสิบหกประกอบด้วยสัญลักษณ์ 16 แบบดังนี้:

  • 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F
    โดยที่ A หมายถึง 10, B หมายถึง 11, …, F หมายถึง 15

การแปลงเลขฐานสิบหกเป็นฐานสิบ

ตัวอย่าง การแปลง 0x2F เป็นฐานสิบ:

  • 0x2F = (2 × 16) + (15 × 1) = 47

การแปลงเลขฐานสิบเป็นฐานสิบหก

วิธีแปลง 47 เป็นเลขฐานสิบหก:

  1. หารด้วย 16 (47 ÷ 16 = 2 เศษ 15)
  2. นำผลหารไปเป็นหลักบน และเศษไปเป็นหลักล่าง
  • ผลลัพธ์: 0x2F

4. การเขียนค่าคงที่ (Literal) แบบเลขฐานสิบหกในภาษา C

วิธีเขียน Literal

ในภาษา C เลขฐานสิบหกเขียนในรูปแบบดังนี้:

int hexValue = 0x1A; // เลขฐานสิบหก "26"

การแสดงผลเลขฐานสิบหกด้วย printf

ใช้ฟังก์ชัน printf เพื่อแสดงผลเลขฐานสิบหก:

#include <stdio.h>

int main() {
    int hexValue = 0x1A;
    printf("เลขฐานสิบหก: %X\n", hexValue); // แสดงด้วยตัวอักษรพิมพ์ใหญ่
    printf("เลขฐานสิบหก: %x\n", hexValue); // แสดงด้วยตัวอักษรพิมพ์เล็ก
    return 0;
}

ผลลัพธ์:

เลขฐานสิบหก: 1A
เลขฐานสิบหก: 1a

ตัวอย่างการกำหนดค่าให้ตัวแปรชนิดจำนวนเต็ม

เลขฐานสิบหกสามารถกำหนดให้กับตัวแปรชนิดจำนวนเต็มได้

int num = 0xFF; // มีค่าเท่ากับ 255

5. เลขฐานสิบหกกับการดำเนินการบิต

การใช้บิตมาสก์ (Bitmask)

เลขฐานสิบหกถูกใช้บ่อยในการทำบิตมาสก์ ตัวอย่างเช่น:

#include <stdio.h>

int main() {
    unsigned char value = 0xAF; // "AF" ในเลขฐานสิบหก
    unsigned char mask = 0x0F;  // มาสก์เพื่อดึง 4 บิตล่าง

    unsigned char result = value & mask;
    printf("ผลลัพธ์: 0x%X\n", result); // ผลคือ "0x0F"
    return 0;
}

การตั้งค่าบิตแฟล็ก

หากต้องการตั้งค่าบิตใดบิตหนึ่งให้เป็น 1:

unsigned char flags = 0x00;
flags |= 0x10; // ตั้งค่าบิตที่ 4 ให้เป็น 1

6. เลขฐานสิบหกกับจำนวนทศนิยมลอยตัว

การแสดงจำนวนทศนิยมลอยตัวในรูปแบบเลขฐานสิบหกมีวิธีพิเศษ แต่สามารถใช้ printf ได้:

#include <stdio.h>

int main() {
    double value = 123.456;
    printf("รูปแบบเลขฐานสิบหก: %a\n", value);
    return 0;
}

ตัวอย่างผลลัพธ์:

รูปแบบเลขฐานสิบหก: 0x1.ed70a3d70a3d7p+6

7. ตัวอย่างการประยุกต์ใช้เลขฐานสิบหก

การวิเคราะห์เมมโมรีดัมพ์ (Memory Dump)

ตัวอย่างการใช้เลขฐานสิบหกเพื่อตรวจสอบเนื้อหาหน่วยความจำระหว่างการดีบัก:

#include <stdio.h>

void dumpMemory(void* ptr, size_t size) {
    unsigned char* byte = (unsigned char*)ptr;
    for (size_t i = 0; i < size; i++) {
        printf("%02X ", byte[i]);
        if ((i + 1) % 16 == 0) printf("\n");
    }
}

int main() {
    int data = 0x12345678;
    dumpMemory(&data, sizeof(data));
    return 0;
}

8. สรุป

บทความนี้ได้อธิบายความรู้พื้นฐานและตัวอย่างการประยุกต์ใช้เลขฐานสิบหกในภาษา C แล้ว เลขฐานสิบหกไม่เพียงแต่ใช้แทนค่าตัวเลข แต่ยังมีประโยชน์ในงานจัดการบิตและการดีบักอีกด้วย การเข้าใจเลขฐานสิบหกจะช่วยให้คุณเขียนโปรแกรมภาษา C ได้มีประสิทธิภาพมากขึ้น

FAQ: คำถามที่พบบ่อยเกี่ยวกับเลขฐานสิบหกในภาษา C

Q1: ถ้าลืมใส่ 0x ตอนประกาศเลขฐานสิบหกจะเกิดอะไรขึ้น?

ถ้าลืมใส่ 0x (หรือ 0X) ตัวเลขจะถูกตีความเป็นเลขฐานสิบ เช่น:

int value = 123; // ถูกตีความเป็นเลขฐานสิบ 123

หากต้องการให้เป็นเลขฐานสิบหก ต้องใส่ 0x เสมอ

Q2: จะป้อนเลขฐานสิบหก (scanf) ในภาษา C ได้อย่างไร?

ใช้ scanf กับฟอร์แมต %x เช่น:

#include <stdio.h>

int main() {
    int value;
    printf("กรุณาป้อนเลขฐานสิบหก (เช่น 0x1A): ");
    scanf("%x", &value);
    printf("ค่าที่ป้อน (ฐานสิบ): %d\n", value);
    return 0;
}

Q3: จะแปลงตัวเลขเป็นสตริงเลขฐานสิบหกได้อย่างไร?

ใช้ sprintf หรือฟังก์ชันจัดการสตริง เช่น:

#include <stdio.h>

int main() {
    int value = 255;
    char hexStr[10];
    sprintf(hexStr, "%X", value);
    printf("สตริงเลขฐานสิบหก: %s\n", hexStr);
    return 0;
}

Q4: ถ้าเลขฐานสิบหกมีหลักไม่ครบจะเกิดอะไรขึ้น?

ไม่มีปัญหา เช่น 0xA เท่ากับ 0x000A แต่เพื่อความชัดเจนในการอ่านโค้ด อาจเติมศูนย์นำหน้า

Q5: สาเหตุหลักของข้อผิดพลาดเมื่อใช้เลขฐานสิบหกในภาษา C คืออะไร?

  1. ลืมใส่ 0x — ควรใส่ทุกครั้ง
  2. ใช้ฟอร์แมตไม่ตรง — เช่นใช้ %d แทนที่จะใช้ %x หรือ %X
  3. ชนิดตัวแปรไม่ตรง — ควรใช้ unsigned เมื่อจำเป็น

Q6: วิธีง่ายๆ ในการแปลงเลขฐานสิบเป็นฐานสิบหก?

ใช้ printf เช่น:

#include <stdio.h>

int main() {
    int decimalValue = 42;
    printf("ฐานสิบ: %d -> ฐานสิบหก: %X\n", decimalValue, decimalValue);
    return 0;
}

Q7: สามารถใช้เลขฐานสิบหกแทนค่าติดลบได้หรือไม่?

ได้ โดยค่าติดลบจะถูกเก็บในรูปแบบ Two’s complement เช่น:

#include <stdio.h>

int main() {
    int negativeValue = -16;
    printf("ฐานสิบ: %d -> ฐานสิบหก: %X\n", negativeValue, negativeValue);
    return 0;
}

ผลลัพธ์ FFFFFFF0 คือการแทนค่าติดลบด้วย Two’s complement

Q8: จะใช้เลขฐานสิบหกในอาเรย์ได้อย่างไร?

สามารถกำหนดค่าเลขฐานสิบหกในอาเรย์ได้โดยตรง เช่น:

#include <stdio.h>

int main() {
    unsigned char hexArray[] = {0x1A, 0x2B, 0x3C, 0x4D};

    for (int i = 0; i < sizeof(hexArray); i++) {
        printf("อาเรย์[%d]: 0x%X\n", i, hexArray[i]);
    }
    return 0;
}
年収訴求