Trong ngôn ngữ lập trình C kiểu dữ liệu nào trong các kiểu sau có miền giá trị lớn nhất

Phạm vi giá trị các kiểu dữ liệu trong C/C++ là một vấn đề mà rất ít bạn quan tâm. Nhưng đây lại là một kiến thức rất quan trọng mà các lập trình viên nên biết. Không biết các bạn đã nghe tới vấn đề bị “tràn số” hay chưa. Để tránh bị lỗi tràn số, các bạn cần biết phạm vi giá trị các kiểu dữ liệu trong ngôn ngữ lập trình.

Lỗi tràn số trong lập trình

Tràn số là hiện tượng biến được gán giá trị nằm ngoài khoảng giá trị thuộc phạm vi của kiểu dữ liệu của biến đó. Đây là một lỗi khá phổ biến đối với các bạn mới học lập trình. Hình ảnh dưới đây mang tính chất mình họa cho lỗi này.

Trong ngôn ngữ lập trình C kiểu dữ liệu nào trong các kiểu sau có miền giá trị lớn nhất
Hiện tượng tràn số trong lập trình(Overflow)

Để giúp các bạn chưa biết về hiện tượng tràn số, mình sẽ lấy ví dụ code C++ với kiểu dữ liệu char. Chắc nhiều bạn đã biết char có kích thước 1 byte = 8 bits. Tức có thể biểu diễn 28 giá trị khác nhau. Ta lại chia đôi 2 miền âm dương ra. Tức là từ -27 đến 27 – 1. Bởi vì phía bên nửa dương cần biểu diễn cho cả số 0 nữa.

Ví dụ về lỗi tràn số

#include <iostream>

using namespace std;

int main(){

    char s = 97;

    cout << (int)s << '\n';

    cout << "Kiem tra char overflow c++\n";

    for(char i = 127; i <= 150; ++i){

        cout << (int)i << '\n';

    }

}

Các bạn nghĩ chương trình này sẽ in ra gì? Vòng for kia sẽ lặp bao nhiêu lần?

char s = 97;

cout << (int)s << '\n';

>>> 97

cout << s << '\n';

>>> a

Với s = 97, mình sẽ in ra được số 97 nếu ép kiểu về int, nếu không sẽ in ra chữ ‘a’. Do mã ASCII của a = 97.

Quay lại với câu hỏi trên. Đáp án là vòng lặp này sẽ lặp vô tận. Vì giá trị lớn nhất của char là 127. Khi nó nhận giá trị từ 128 trở lên, sẽ xảy ra hiện tượng tràn số.

Nếu không tin, bạn hãy chạy thử. Hoặc đơn giản hơn, thử mấy dòng code này coi nó in ra gì:

#include <iostream>

using namespace std;

int main(){

    char s = 128;

    cout << (int)s << '\n';

    s = 129;

    cout << (int)s << '\n';

    s = 130;

    cout << (int)s << '\n';

}

Đây là output bạn nhận được. Đó là hậu quả do tràn số gây ra.

Chú ý: Hiện tượng tràn số có thể xảy ra ở tất cả các ngôn ngữ lập trình. Với các ngôn ngữ lập trình bậc cao, bản thân nó đã có cơ chế kiểm soát nên có thể bạn không thấy.

Nếu bạn đang quan tâm tới lập trình C/C++, hãy đọc các bài viết hay khác tại chuyên mục lập trình C/C++.

Trong ngôn ngữ lập trình C kiểu dữ liệu nào trong các kiểu sau có miền giá trị lớn nhất
Phạm vi giá trị các kiểu dữ liệu

Vậy làm gì để tránh bị tràn số trong lập trình nói chung? Bạn cần phải nắm được phạm vi giá trị các kiểu dữ liệu trong mỗi ngôn ngữ lập trình. Về cơ bản nhiều kiểu dữ liệu trong các ngôn ngữ lập trình là giống nhau. Do vậy, trong bài viết này, mình chỉ trình bày về phạm vi giá trị các kiểu dữ liệu trong C/C++.

Bảng phạm vi giá trị các kiểu dữ liệu trong C/C++

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

Data Type                              Range                      Macro for min value           Macro for max value

char                                -128 to +127                        CHAR_MIN                      CHAR_MAX

short char                          -128 to +127                       SCHAR_MIN                     SCHAR_MAX

unsigned char                         0  to 255                             0                        UCHAR_MAX

short int                         -32768 to +32767                      SHRT_MIN                      SHRT_MAX

unsigned short int                    0  to  65535                          0                        USHRT_MAX

int                          -2147483648 to +2147483647                  INT_MIN                       INT_MAX

unsigned int                          0  to  4294967295                     0                         UINT_MAX

long int            -9223372036854775808 to +9223372036854775807        LONG_MIN                      LONG_MAX

unsigned long int                     0  to  18446744073709551615           0                        ULONG_MAX

long long int       -9223372036854775808 to +9223372036854775807       LLONG_MIN                     LLONG_MAX

unsigned long long int                0  to  18446744073709551615           0                       ULLONG_MAX

float                        1.17549e-38 to  3.40282e+38                 FLT_MIN                       FLT_MAX

float(negative)             -1.17549e-38 to -3.40282e+38                -FLT_MIN                      -FLT_MAX

double                      2.22507e-308 to  1.79769e+308                DBL_MIN                       DBL_MAX

double(negative)           -2.22507e-308 to -1.79769e+308               -DBL_MIN                      -DBL_MAX

Để xem phạm vi của các kiểu dữ liệu này, bạn có thể sử dụng các Marco ở bảng trên. Dưới đây là code ví dụ:

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

// C++ code to demonstrate the macros for data types

#include<iostream>

#include<limits.h> // for int,char macros

#include<float.h> // for float,double macros

using namespace std;

int main()

{

// Displaying ranges with the help of macros

cout << "char ranges from : " << CHAR_MIN << " to " << CHAR_MAX;

cout << "\n\nshort char ranges from : " << SCHAR_MIN << " to " << SCHAR_MAX;

cout << "\n\nunsigned char ranges from : " << 0 << " to " << UCHAR_MAX;

cout << "\n\n\nshort int ranges from : " << SHRT_MIN << " to " << SHRT_MAX;

cout << "\n\nunsigned short int ranges from : " << 0 << " to " << USHRT_MAX;

cout << "\n\nint ranges from : " << INT_MIN << " to " << INT_MAX;

cout << "\n\nunsigned int ranges from : " << 0 << " to " << UINT_MAX;

cout << "\n\nlong int ranges from : " << LONG_MIN << " to " << LONG_MAX;

cout << "\n\nunsigned long int ranges from : " << 0 << " to " << ULONG_MAX;

cout << "\n\nlong long int ranges from : " << LLONG_MIN << " to " << LLONG_MAX;

cout << "\n\nunsigned long long int ranges from : " << 0 << " to " << ULLONG_MAX;

cout << "\n\n\nfloat ranges from : " << FLT_MIN << " to " << FLT_MAX;

cout << "\n\nnegative float ranges from : " << -FLT_MIN << " to " << -FLT_MAX;

cout << "\n\ndouble ranges from : " << DBL_MIN << " to " << DBL_MAX;

cout << "\n\nnegative double ranges from : " << -DBL_MIN << " to " << +DBL_MAX;

return 0;

}

Output:

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

char ranges from : -128 to 127

short char ranges from : -128 to 127

unsigned char ranges from : 0 to 255

short int ranges from : -32768 to 32767

unsigned short int ranges from : 0 to 65535

int ranges from : -2147483648 to 2147483647

unsigned int ranges from : 0 to 4294967295

long int ranges from : -9223372036854775808 to 9223372036854775807

unsigned long int ranges from : 0 to 18446744073709551615

long long int ranges from : -9223372036854775808 to 9223372036854775807

unsigned long long int ranges from : 0 to 18446744073709551615

float ranges from : 1.17549e-38 to 3.40282e+38

negative float ranges from : -1.17549e-38 to -3.40282e+38

double ranges from : 2.22507e-308 to 1.79769e+308

negative double ranges from : -2.22507e-308 to 1.79769e+308

Giải thích phạm vi của kiểu dữ liệu

Mình sẽ lấy ví dụ với kiểu char cho nhỏ nhé. Mình cần các bạn biết về hoán vị nữa.

Như các bạn biết, 1 bit trong lập trình sẽ biểu diễn được 2 giá trị: 0 hoặc 1. Tức là biểu diễn được 21 giá trị.

Vậy 2 bits sẽ biểu diễn được 4 giá trị: 00, 01, 10 và 11. Tức là biểu diễn được 22 giá trị.

Như vậy, 1 byte = 8 bits sẽ biểu diễn được 28 giá trị khác nhau.

Mà máy tính lưu giá trị mã bit 0 và 1. Tức dạng nhị phân. Do đó 00 = 0, 01 = 1, 10 = 2, 11 = 3 trong cơ số 10. Như vậy, giá trị lớn nhất mà 1 byte có thể biểu diễn là 11111111 = 2^7 + 2^6 + 2^5 + 2^4 + 2^3 + 2^2 + 2^1 + 2^0 = 255.

Đó là lý do kiểu unsigned char có phạm vi giá trị từ 0 đến 255. Còn kiểu char do có cả miền âm nên sẽ bị chia đôi(-128 đến 127). Phần dương bị hụt 1 giá trị do cần biểu diễn cả số 0.

Kết luận

Như vậy, trong bài viết này Nguyễn Văn Hiếu đã giúp các bạn biết được phạm vi giá trị các kiểu dữ liệu trong ngôn ngữ C++. Đồng thời, các bạn cũng đã biết về hiện tượng tràn số và cách để tránh bị tràn số. Còn nếu bạn nào chưa biết cách thì để lại câu hỏi ở bình luận nhé.

Chúc các bạn học tập tốt!

Tài liệu tham khảo

[1]. https://www.geeksforgeeks.org/data-type-ranges-and-their-macros-in-c/