Đây thực sự là một điều kỳ quặc của VBA. Tôi ngạc nhiên là tôi chưa bao giờ đụng vào chuyện này.
Dim x As Long
x = 24 * 60 * 60 ' Overflow
x = 32767 + 1 ' Overflow.
x = 32768 + 1 ' Works fine!
Vì vậy, nó trông giống như *
và +
khai thác trở lại một Integer trong hai ví dụ đầu tiên. Chắc chắn, trong file trợ giúp cho các nhà điều hành *
(tương tự cho các nhà điều hành +
):
result = number1 * number2
[...]
The data type of result is usually the same as that of the most precise expression.
literals bạn 24, 60 và 60 là tất cả các loại Integer theo mặc định, vì vậy bạn *
(hoặc +
) điều hành trả về một số nguyên, nó tràn vì kết quả lớn hơn 32,767.
Tuy nhiên, chữ cái 32.768 trong ví dụ thứ ba ở trên mặc định là Loại dài (vì nó quá lớn để là Số nguyên) và do đó +
trả về giá trị Dài; không tràn.
Các tập tin trợ giúp cũng nói điều này:
If [...] the data type of result is an Integer variant that overflows its legal range [...] Then result is [...] converted to a Long variant.
Nhấn mạnh tôi. Bây giờ quy tắc nhỏ này có vẻ giống như ý thức thông thường, và bất cứ ai sẽ giả định hợp lý rằng nó áp dụng trong trường hợp của bạn. Nhưng các con số của bạn thuộc kiểu Integer, không phải là Variant/Integer, do đó VBA không áp dụng quy tắc này! Làm cho hoàn toàn không có ý nghĩa với tôi, nhưng đó là cách nó được, và đó là những gì tài liệu nói.
Giải pháp: thực hiện một trong các đối số của toán tử *
có loại chính xác hơn Integer (ví dụ: Long) và sự cố sẽ biến mất.
x = CLng(24) * 60 * 60 ' Result is Long, works fine.
Trong thực tế, và điều này có lẽ là lý do tại sao tôi đã không bao giờ đụng vào không minh bạch này, tôi thực hiện một thói quen tuyên bố tất cả các biến Integer của tôi như dài thay vào đó, trừ khi có một mối quan tâm cụ thể mà có Longs thay vì Số nguyên sẽ gây ra vấn đề với việc sử dụng bộ nhớ hoặc thời gian thực hiện (gần như không bao giờ là trường hợp). Cấp, điều này sẽ không giúp đỡ trong trường hợp khi bạn hoạt động trên literals nhỏ hơn 32,768, bởi vì họ mặc định để loại Integer.
Bạn yêu cầu a comment Biến thể/số nguyên là gì. Biến thể về cơ bản là một loại container cho bất kỳ loại dữ liệu nào khác. Trong trường hợp cụ thể mà bạn thực hiện nó chứa một Integer:
Dim a As Variant ' a is now Empty
a = CInt(32767) ' a is now Variant/Integer
x = a + 1 ' works fine
Nhưng như đã nói ở trên, một đồng bằng cũ Integer kích hoạt lỗi tràn bộ nhớ:
Dim b As Integer
b = 32767
x = b + 1 ' overflow
Tiếp tục cho việc này. - Nếu tôi đặt msgbox 26 * 60^2 trong cửa sổ ngay lập tức thì không có vấn đề gì cả. Nó là một thứ tự của vấn đề ưu tiên? Điều đó có vẻ khó xảy ra ... –
Đó là bởi vì toán tử '^' trả về một Double, điều này sẽ tránh được vấn đề được mô tả trong câu trả lời của tôi bên dưới. –