<inttypes.h> Các phép chuyển đổi số nguyên thêm| Hàm | Mô tả |
|---|---|
imaxabs() |
Tính giá trị tuyệt đối của một intmax_t |
imaxdiv() |
Tính thương và số dư của các intmax_t |
strtoimax() |
Chuyển string sang kiểu intmax_t |
strtoumax() |
Chuyển string sang kiểu uintmax_t |
wcstoimax() |
Chuyển wide string sang kiểu intmax_t |
wcstoumax() |
Chuyển wide string sang kiểu uintmax_t |
Header này làm các phép chuyển đổi sang số nguyên cỡ lớn nhất, chia với số nguyên cỡ lớn nhất, và cũng cung cấp format specifier cho printf() và scanf() cho một loạt kiểu được định nghĩa trong <stdint.h>.
Header <stdint.h> được include bởi header này.
Mấy macro này là để giúp printf() và scanf() khi bạn dùng một kiểu như int_least16_t… bạn dùng format specifier gì?
Bắt đầu với printf()—mấy macro này bắt đầu bằng PRI rồi theo sau là format specifier mà bạn thường dùng cho kiểu đó. Cuối cùng, thêm số bit.
Ví dụ, format specifier cho số nguyên 64-bit là PRId64—chữ d là vì thường bạn in số nguyên với "%d".
Một số nguyên không dấu 16-bit có thể được in với PRIu16.
Mấy macro này mở rộng thành string literal. Ta có thể tận dụng việc C tự động nối các string literal kề nhau và dùng các specifier này như sau:
#include <stdio.h> // cho printf()
#include <inttypes.h>
int main(void)
{
int16_t x = 32;
printf("The value is %" PRId16 "!\n", x);
}Không có gì ma thuật xảy ra ở dòng 8 bên trên đâu. Thật vậy, nếu tôi in giá trị của macro:
printf("%s\n", PRId16);ta nhận được cái này trên hệ của tôi:
hdlà một format specifier của printf() có nghĩa “số nguyên có dấu ngắn”.
Nên quay lại dòng 8, sau khi nối string literal, nó y hệt như tôi đã gõ:
Đây là bảng mọi macro bạn có thể dùng cho format specifier của printf()… thay số bit vào N, thường là 8, 16, 32, hoặc 64.
PRIdN |
PRIdLEASTN |
PRIdFASTN |
PRIdMAX |
PRIdPTR |
PRIiN |
PRIiLEASTN |
PRIiFASTN |
PRIiMAX |
PRIiPTR |
PRIoN |
PRIoLEASTN |
PRIoFASTN |
PRIoMAX |
PRIoPTR |
PRIuN |
PRIuLEASTN |
PRIuFASTN |
PRIuMAX |
PRIuPTR |
PRIxN |
PRIxLEASTN |
PRIxFASTN |
PRIxMAX |
PRIxPTR |
PRIXN |
PRIXLEASTN |
PRIXFASTN |
PRIXMAX |
PRIXPTR |
Để ý lần nữa là chữ chữ thường ở giữa đại diện cho các format specifier thông thường bạn truyền cho printf(): d, i, o, u, x, và X.
Và ta có một bộ macro tương tự cho scanf() để đọc các kiểu này:
SCNdN |
SCNdLEASTN |
SCNdFASTN |
SCNdMAX |
SCNdPTR |
SCNiN |
SCNiLEASTN |
SCNiFASTN |
SCNiMAX |
SCNiPTR |
SCNoN |
SCNoLEASTN |
SCNoFASTN |
SCNoMAX |
SCNoPTR |
SCNuN |
SCNuLEASTN |
SCNuFASTN |
SCNuMAX |
SCNuPTR |
SCNxN |
SCNxLEASTN |
SCNxFASTN |
SCNxMAX |
SCNxPTR |
Quy tắc là với mỗi kiểu được định nghĩa trong <stdint.h> sẽ có các macro printf() và scanf() tương ứng được định nghĩa ở đây.
imaxabs()Tính giá trị tuyệt đối của một intmax_t
#include <inttypes.h>
intmax_t imaxabs(intmax_t j);Khi bạn cần giá trị tuyệt đối của kiểu số nguyên lớn nhất trên hệ thống, đây là hàm dành cho bạn.
Spec ghi chú rằng nếu giá trị tuyệt đối của số không biểu diễn được, hành vi là undefined. Chuyện này xảy ra nếu bạn thử lấy giá trị tuyệt đối của số âm nhỏ nhất có thể trên hệ thống biểu diễn bù hai (two’s complement).
Trả về giá trị tuyệt đối của đầu vào, \(|j|\).
#include <stdio.h>
#include <inttypes.h>
int main(void)
{
intmax_t j = -3490;
printf("%jd\n", imaxabs(j)); // 3490
}imaxdiv()Tính thương và số dư của các intmax_t
#include <inttypes.h>
imaxdiv_t imaxdiv(intmax_t numer, intmax_t denom);Khi bạn muốn làm phép chia nguyên và lấy số dư trong cùng một phép, hàm này sẽ làm cho bạn.
Nó tính numer/denom và numer%denom rồi trả về kết quả trong một struct kiểu imaxdiv_t.
Struct này có hai field kiểu imaxdiv_t, quot và rem, mà bạn dùng để lấy các giá trị mong muốn.
Trả về một imaxdiv_t chứa thương và số dư của phép toán.
#include <stdio.h>
#include <inttypes.h>
int main(void)
{
intmax_t numer = INTMAX_C(3490);
intmax_t denom = INTMAX_C(17);
imaxdiv_t r = imaxdiv(numer, denom);
printf("Quotient: %jd, remainder: %jd\n", r.quot, r.rem);
}Output:
Quotient: 205, remainder: 5strtoimax() strtoumax()
Chuyển string sang kiểu intmax_t và uintmax_t
#include <inttypes.h>
intmax_t strtoimax(const char * restrict nptr, char ** restrict endptr,
int base);
uintmax_t strtoumax(const char * restrict nptr, char ** restrict endptr,
int base);Mấy cái này hoạt động y hệt họ hàm strtol(), chỉ khác là trả về intmax_t hoặc uintmax_t.
Xem trang tham chiếu strtol() để biết chi tiết.
Trả về string đã chuyển dưới dạng intmax_t hoặc uintmax_t.
Nếu kết quả nằm ngoài miền giá trị, giá trị trả về sẽ là INTMAX_MAX, INTMAX_MIN, hoặc UINTMAX_MAX, tuỳ trường hợp. Và biến errno sẽ được set thành ERANGE.
Ví dụ sau chuyển một số cơ số 10 sang intmax_t. Rồi nó thử chuyển một số cơ số 2 không hợp lệ, bắt lỗi.
#include <stdio.h>
#include <inttypes.h>
int main(void)
{
intmax_t r;
char *endptr;
// Số cơ số 10 hợp lệ
r = strtoimax("123456789012345", &endptr, 10);
if (*endptr != '\0')
printf("Invalid digit: %c\n", *endptr);
else
printf("Value is %jd\n", r);
// Số nhị phân sau chứa chữ số không hợp lệ
r = strtoimax("0100102010101101", &endptr, 2);
if (*endptr != '\0')
printf("Invalid digit: %c\n", *endptr);
else
printf("Value is %jd\n", r);
}Output:
Value is 123456789012345
Invalid digit: 2wcstoimax() wcstoumax()
Chuyển wide string sang kiểu intmax_t và uintmax_t
#include <stddef.h> // cho wchar_t
#include <inttypes.h>
intmax_t wcstoimax(const wchar_t * restrict nptr,
wchar_t ** restrict endptr, int base);
uintmax_t wcstoumax(const wchar_t * restrict nptr,
wchar_t ** restrict endptr, int base);Mấy cái này hoạt động y hệt họ hàm wcstol(), chỉ khác là trả về intmax_t hoặc uintmax_t.
Xem trang tham chiếu wcstol() để biết chi tiết.
Trả về wide string đã chuyển dưới dạng intmax_t hoặc uintmax_t.
Nếu kết quả nằm ngoài miền giá trị, giá trị trả về sẽ là INTMAX_MAX, INTMAX_MIN, hoặc UINTMAX_MAX, tuỳ trường hợp. Và biến errno sẽ được set thành ERANGE.
Ví dụ sau chuyển một số cơ số 10 sang intmax_t. Rồi nó thử chuyển một số cơ số 2 không hợp lệ, bắt lỗi.
#include <wchar.h>
#include <inttypes.h>
int main(void)
{
intmax_t r;
wchar_t *endptr;
// Số cơ số 10 hợp lệ
r = wcstoimax(L"123456789012345", &endptr, 10);
if (*endptr != '\0')
wprintf(L"Invalid digit: %lc\n", *endptr);
else
wprintf(L"Value is %jd\n", r);
// Số nhị phân sau chứa chữ số không hợp lệ
r = wcstoimax(L"0100102010101101", &endptr, 2);
if (*endptr != '\0')
wprintf(L"Invalid digit: %lc\n", *endptr);
else
wprintf(L"Value is %jd\n", r);
}Value is 123456789012345
Invalid digit: 2