((A + (b & 255)) & 255) có giống với ((a + b) & 255) không?


92

Tôi đang duyệt một số mã C ++ và tìm thấy một cái gì đó như thế này:

(a + (b & 255)) & 255

Đôi AND khiến tôi khó chịu, vì vậy tôi nghĩ đến:

(a + b) & 255

( ablà số nguyên không dấu 32 bit)

Tôi nhanh chóng viết một kịch bản thử nghiệm (JS) để xác nhận lý thuyết của mình:

for (var i = 0; i < 100; i++) {
    var a = Math.ceil(Math.random() * 0xFFFF),
        b = Math.ceil(Math.random() * 0xFFFF);

    var expr1 = (a + (b & 255)) & 255,
        expr2 = (a + b) & 255;

    if (expr1 != expr2) {
        console.log("Numbers " + a + " and " + b + " mismatch!");
        break;
    }
}

Trong khi kịch bản xác nhận giả thuyết của tôi (cả hai phép toán đều bằng nhau), tôi vẫn không tin tưởng nó, bởi vì 1) ngẫu nhiên và 2) Tôi không phải là nhà toán học, tôi không biết mình đang làm gì .

Ngoài ra, xin lỗi vì tiêu đề Lisp-y. Hãy chỉnh sửa nó.


4
Chữ viết đó là ngôn ngữ gì? Có Math.random()trả về một số nguyên hoặc một số kép trên [0,1) không? Tôi không nghĩ rằng kịch bản của bạn (tốt nhất mà tôi có thể nói) phản ánh vấn đề mà bạn đặt ra.
Brick

7
Mã c / c ++ là gì? Họ là những ngôn ngữ khác nhau.
Weather Vane

14
Bạn không thể tái tạo hành vi mà bạn đang cố gắng kiểm tra trong JS. Đó là lý do tại sao mọi người chỉ có bạn về sự lựa chọn ngôn ngữ. JS không được nhập mạnh và câu trả lời phụ thuộc rất nhiều vào kiểu của các biến trong C / C ++. JS hoàn toàn vô nghĩa với câu hỏi mà bạn đã hỏi.
Brick

4
@WeatherVane Đó là mã giả thiết yếu, sử dụng tên hàm Javascript. Câu hỏi của anh ấy là về hành vi của &+trên các số nguyên không dấu trong C và C ++.
Barmar

11
Hãy nhớ rằng "Tôi đã viết một chương trình thử nghiệm và nhận được câu trả lời mà tôi mong đợi cho tất cả các đầu vào có thể có" không thực sự đảm bảo rằng điều gì đó sẽ hoạt động như bạn mong đợi. Hành vi không xác định có thể khó chịu như vậy; chỉ đưa ra kết quả bất ngờ sau khi bạn đã thuyết phục xong bản thân rằng mã của bạn là đúng.

Câu trả lời:


78

Họ giống nhau. Đây là một bằng chứng:

Đầu tiên lưu ý danh tính (A + B) mod C = (A mod C + B mod C) mod C

Hãy trình bày lại vấn đề bằng cách liên quan đến a & 255như đứng cho a % 256. Điều này đúng vì akhông có dấu.

Vì vậy, (a + (b & 255)) & 255(a + (b % 256)) % 256

Điều này giống như (a % 256 + b % 256 % 256) % 256(Tôi đã áp dụng danh tính được nêu ở trên: lưu ý rằng mod%tương đương với các loại không dấu.)

Điều này đơn giản hóa việc (a % 256 + b % 256) % 256trở thành (a + b) % 256(áp dụng lại danh tính). Sau đó, bạn có thể đặt lại toán tử bitwise để đưa ra

(a + b) & 255

hoàn thành bằng chứng.


81
Đó là bằng chứng toán học, bỏ qua khả năng tràn. Hãy cân nhắc A=0xFFFFFFFF, B=1, C=3. Danh tính đầu tiên không giữ. (Overflow sẽ không thể là một vấn đề đối với số học unsigned, nhưng nó là một điều hơi khác nhau.)
AlexD

4
Trên thực tế, (a + (b & 255)) & 255cũng giống như (a + (b % 256)) % N % 256, trong đó Nmột giá trị lớn hơn giá trị không dấu lớn nhất. (công thức sau có nghĩa là để được hiểu là số học của các số nguyên toán học)

17
Chứng minh toán học như thế này không thích hợp để chứng minh hành vi của số nguyên trên kiến ​​trúc máy tính.
Jack Aidley

25
@JackAidley: Chúng thích hợp khi được thực hiện đúng cách (cái nào thì không, do bỏ qua việc xem xét tràn).

3
@Shaz: Điều đó đúng với kịch bản thử nghiệm, nhưng không phải là một phần của câu hỏi được hỏi.

21

Trong phép cộng, trừ và nhân các số không có dấu vị trí để tạo ra kết quả không dấu, các chữ số có nghĩa hơn của đầu vào không ảnh hưởng đến các chữ số có nghĩa nhỏ hơn của kết quả. Điều này áp dụng cho số học nhị phân cũng giống như số học thập phân. Nó cũng áp dụng cho số học có dấu "phần bù hai", nhưng không áp dụng cho số học có dấu độ lớn.

Tuy nhiên, chúng ta phải cẩn thận khi lấy các quy tắc từ số học nhị phân và áp dụng chúng cho C (Tôi tin rằng C ++ có các quy tắc tương tự như C về nội dung này nhưng tôi không chắc chắn 100%) vì C số học có một số quy tắc phức tạp có thể khiến chúng ta gặp khó khăn. lên. Số học không dấu trong C tuân theo các quy tắc bao quanh nhị phân đơn giản nhưng tràn số học có dấu là hành vi không xác định. Tệ hơn nữa trong một số trường hợp, C sẽ tự động "thăng cấp" một kiểu không dấu thành (đã ký) int.

Hành vi không xác định trong C có thể đặc biệt xảo quyệt. Một trình biên dịch ngu ngốc (hoặc trình biên dịch ở mức tối ưu hóa thấp) có khả năng làm những gì bạn mong đợi dựa trên sự hiểu biết của bạn về số học nhị phân trong khi trình biên dịch tối ưu hóa có thể phá vỡ mã của bạn theo những cách kỳ lạ.


Vì vậy, quay lại công thức trong câu hỏi, tính tương đương phụ thuộc vào các loại toán hạng.

Nếu chúng là các số nguyên không dấu có kích thước lớn hơn hoặc bằng kích thước của intthì hành vi tràn của toán tử cộng được xác định rõ là bao bọc nhị phân đơn giản. Việc chúng ta có che đi 24 bit cao của một toán hạng trước khi thực hiện phép cộng hay không cũng không ảnh hưởng đến các bit thấp của kết quả.

Nếu chúng là số nguyên không dấu có kích thước nhỏ hơn intthì chúng sẽ được thăng cấp thành (có dấu) int. Tràn số nguyên có dấu là hành vi không xác định nhưng ít nhất trên mọi nền tảng, tôi đã gặp phải sự khác biệt về kích thước giữa các loại số nguyên khác nhau đủ lớn để một lần thêm hai giá trị được thăng hạng sẽ không gây tràn. Vì vậy, một lần nữa chúng ta có thể quay trở lại đối số số học nhị phân đơn giản để coi các câu lệnh là tương đương.

Nếu chúng là các số nguyên có dấu có kích thước nhỏ hơn int thì không thể xảy ra tràn lần nữa và khi triển khai hai phần bổ sung, chúng ta có thể dựa vào đối số số học nhị phân chuẩn để nói rằng chúng là tương đương. Về cường độ dấu hiệu hoặc những thứ bổ sung cho việc triển khai, chúng sẽ không tương đương.

OTOH nếu ablà các số nguyên có dấu có kích thước lớn hơn hoặc bằng kích thước của int thì ngay cả trên các triển khai bổ sung hai bên vẫn có trường hợp một câu lệnh sẽ được xác định rõ trong khi câu lệnh kia là hành vi không xác định.


20

Bổ đề: a & 255 == a % 256cho trái dấu a.

Unsigned acó thể được viết lại như m * 0x100 + bmột số chưa được ký m, b, 0 <= b < 0xff, 0 <= m <= 0xffffff. Nó theo sau từ cả hai định nghĩa đó a & 255 == b == a % 256.

Ngoài ra, chúng tôi cần:

  • tài sản phân phối: (a + b) mod n = [(a mod n) + (b mod n)] mod n
  • định nghĩa của phép cộng không dấu, về mặt toán học: (a + b) ==> (a + b) % (2 ^ 32)

Như vậy:

(a + (b & 255)) & 255 = ((a + (b & 255)) % (2^32)) & 255      // def'n of addition
                      = ((a + (b % 256)) % (2^32)) % 256      // lemma
                      = (a + (b % 256)) % 256                 // because 256 divides (2^32)
                      = ((a % 256) + (b % 256 % 256)) % 256   // Distributive
                      = ((a % 256) + (b % 256)) % 256         // a mod n mod n = a mod n
                      = (a + b) % 256                         // Distributive again
                      = (a + b) & 255                         // lemma

Vì vậy, có, nó là sự thật. Đối với số nguyên không dấu 32 bit.


Còn các kiểu số nguyên khác thì sao?

  • Đối với số nguyên 64-bit không dấu, tất cả các điều trên cũng áp dụng, chỉ cần thay thế 2^64cho 2^32.
  • Đối với các số nguyên không dấu 8 và 16 bit, việc bổ sung bao gồm việc thăng hạng lên int. Điều này intchắc chắn sẽ không bị tràn hoặc bị âm trong bất kỳ hoạt động nào trong số này, vì vậy tất cả chúng đều vẫn hợp lệ.
  • Đối với chữ ký số nguyên, nếu một trong hai a+bhoặc a+(b&255)tràn, đó là hành vi không xác định. Vì vậy, sự bình đẳng không thể giữ - có những trường hợp (a+b)&255là hành vi không xác định nhưng (a+(b&255))&255không phải.

17

Vâng, (a + b) & 255là tốt.

Ghi nhớ ngoài trường học? Bạn thêm số từng chữ số và thêm giá trị thực vào cột chữ số tiếp theo. Không có cách nào để cột chữ số sau này (quan trọng hơn) ảnh hưởng đến cột đã được xử lý. Bởi vì điều này, nó không tạo ra sự khác biệt nếu bạn chỉ xóa các chữ số trong kết quả hoặc đầu tiên trong một đối số.


Điều trên không phải lúc nào cũng đúng, tiêu chuẩn C ++ cho phép thực hiện có thể phá vỡ điều này.

Một Deathstation 9000 như vậy : - ) sẽ phải sử dụng 33-bit int, nếu OP có nghĩa là unsigned short"số nguyên không dấu 32-bit". Nếu unsigned intcó nghĩa là, DS9K sẽ phải sử dụng 32-bit intvà 32-bit unsigned intvới một bit đệm. (Các số nguyên không dấu được yêu cầu phải có cùng kích thước với các số đối có dấu của chúng theo §3.9.1 / 3 và các bit đệm được cho phép trong §3.9.1 / 1.) Các kết hợp kích thước và bit đệm khác cũng sẽ hoạt động.

Theo như tôi có thể nói, đây là cách duy nhất để phá vỡ nó, bởi vì:

  • Biểu diễn số nguyên phải sử dụng lược đồ mã hóa "thuần túy nhị phân" (§3.9.1 / 7 và chú thích cuối trang), tất cả các bit ngoại trừ bit đệm và bit dấu phải đóng góp giá trị 2 n
  • Quảng cáo int chỉ được phép nếu intcó thể đại diện cho tất cả các giá trị của kiểu nguồn (§4.5 / 1), do đó intphải có ít nhất 32 bit đóng góp vào giá trị, cộng với một bit dấu.
  • những intkhông thể có bit giá trị hơn (không tính các bit dấu) hơn 32 tuổi, bởi vì khác một sự bổ sung không thể tràn.

2
Ngoài ra còn có nhiều thao tác khác trong đó rác ở các bit cao không ảnh hưởng đến kết quả ở các bit thấp mà bạn quan tâm. Hãy xem phần Hỏi & Đáp này về phần bổ sung của 2 , sử dụng x86 asm làm trường hợp sử dụng, nhưng cũng áp dụng cho số nguyên nhị phân không dấu trong mọi tình huống.
Peter Cordes

2
Mặc dù tất nhiên mọi người đều có quyền phản đối ẩn danh, nhưng tôi luôn đánh giá cao nhận xét như một cơ hội để học hỏi.
alain

2
Đây là câu trả lời / lập luận dễ hiểu nhất, IMO. Việc mang / mượn trong phép cộng / trừ chỉ truyền từ các bit thấp đến các bit cao (từ phải sang trái) trong hệ nhị phân, giống như trong hệ thập phân. IDK tại sao ai đó sẽ phản đối điều này.
Peter Cordes

1
@Bathsheba: CHAR_BIT không bắt buộc phải là 8. Nhưng các kiểu không dấu trong C và C ++ được yêu cầu hoạt động như các số nguyên nhị phân base2 bình thường với độ rộng bit nào đó. Tôi nghĩ rằng yêu cầu UINT_MAX là 2^N-1. (N có thể không được yêu cầu là bội số của CHAR_BIT, tôi quên, nhưng tôi khá chắc chắn rằng tiêu chuẩn yêu cầu rằng sự bao bọc xảy ra theo mô đun một số sức mạnh của 2.) Tôi nghĩ cách duy nhất để bạn có được sự kỳ lạ là thông qua việc thăng cấp lên một loại có chữ ký đủ rộng để chứa ahoặc bnhưng không đủ rộng để chứa a+btrong mọi trường hợp.
Peter Cordes

2
@Bathsheba: vâng, may mắn thay, C-as-portable-assembly-language thực sự hoạt động hầu hết với các loại không dấu. Thậm chí không phải việc triển khai C có chủ đích thù địch có thể phá vỡ điều này. Đó chỉ là những loại có chữ ký khi mọi thứ trở nên khủng khiếp đối với các vụ hack bit thực sự di động trong C và Deathstation 9000 thực sự có thể phá mã của bạn.
Peter Cordes

14

Bạn đã có câu trả lời thông minh: số học không dấu là số học modulo và do đó kết quả sẽ giữ nguyên, bạn có thể chứng minh điều đó bằng toán học ...


Tuy nhiên, một điều thú vị về máy tính là máy tính rất nhanh. Thật vậy, chúng nhanh đến mức có thể liệt kê tất cả các kết hợp hợp lệ của 32 bit trong một khoảng thời gian hợp lý (đừng thử với 64 bit).

Vì vậy, trong trường hợp của bạn, cá nhân tôi chỉ muốn ném nó vào máy tính; Tôi mất ít thời gian hơn để thuyết phục bản thân rằng chương trình là đúng hơn là tự thuyết phục bản thân hơn là bằng chứng toán học là đúng tôi đã không giám sát một chi tiết trong đặc điểm kỹ thuật 1 :

#include <iostream>
#include <limits>

int main() {
    std::uint64_t const MAX = std::uint64_t(1) << 32;
    for (std::uint64_t i = 0; i < MAX; ++i) {
        for (std::uint64_t j = 0; j < MAX; ++j) {
            std::uint32_t const a = static_cast<std::uint32_t>(i);
            std::uint32_t const b = static_cast<std::uint32_t>(j);

            auto const champion = (a + (b & 255)) & 255;
            auto const challenger = (a + b) & 255;

            if (champion == challenger) { continue; }

            std::cout << "a: " << a << ", b: " << b << ", champion: " << champion << ", challenger: " << challenger << "\n";
            return 1;
        }
    }

    std::cout << "Equality holds\n";
    return 0;
}

Điều này liệt kê thông qua tất cả các giá trị có thể có của abtrong không gian 32-bit và kiểm tra xem sự bình đẳng có giữ hay không. Nếu không, nó sẽ in ra trường hợp không hoạt động, bạn có thể sử dụng cái này để kiểm tra sự tỉnh táo.

Và, theo Clang : Bình đẳng được giữ vững .

Hơn nữa, do các quy tắc số học là bất khả tri về độ rộng bit (ở trên intđộ rộng bit), sự bình đẳng này sẽ giữ cho bất kỳ kiểu số nguyên không dấu nào từ 32 bit trở lên, bao gồm cả 64 bit và 128 bit.

Lưu ý: Làm thế nào một trình biên dịch có thể liệt kê tất cả các mẫu 64 bit trong một khung thời gian hợp lý? Nó không thể. Các vòng lặp đã được tối ưu hóa. Nếu không, tất cả chúng ta đã chết trước khi cuộc hành quyết chấm dứt.


Ban đầu tôi chỉ chứng minh điều đó cho các số nguyên không dấu 16 bit; Thật không may, C ++ là một ngôn ngữ điên rồ nơi các số nguyên nhỏ (bitwidths nhỏ hơn int) được chuyển đổi đầu tiên int.

#include <iostream>

int main() {
    unsigned const MAX = 65536;
    for (unsigned i = 0; i < MAX; ++i) {
        for (unsigned j = 0; j < MAX; ++j) {
            std::uint16_t const a = static_cast<std::uint16_t>(i);
            std::uint16_t const b = static_cast<std::uint16_t>(j);

            auto const champion = (a + (b & 255)) & 255;
            auto const challenger = (a + b) & 255;

            if (champion == challenger) { continue; }

            std::cout << "a: " << a << ", b: " << b << ", champion: "
                      << champion << ", challenger: " << challenger << "\n";
            return 1;
        }
    }

    std::cout << "Equality holds\n";
    return 0;
}

Và một lần nữa, theo Clang : Bình đẳng được giữ vững .

Vâng, bạn đi rồi :)


1 Tất nhiên, nếu một chương trình nào đó vô tình kích hoạt Hành vi không xác định, thì điều đó sẽ không chứng minh được nhiều điều.


1
bạn nói nó rất dễ dàng để làm với giá trị 32-bit nhưng thực tế sử dụng 16-bit ...: D
Willi Mentzel

1
@WilliMentzel: Đó là một nhận xét thú vị. Ban đầu tôi muốn nói rằng nếu nó hoạt động với 16 bit thì nó sẽ hoạt động tương tự với 32 bit, 64 bit và 128 bit vì Tiêu chuẩn không có hành vi cụ thể cho các độ rộng bit khác nhau ... tuy nhiên tôi nhớ rằng nó thực sự có đối với độ rộng bit nhỏ hơn độ rộng của int: số nguyên nhỏ lần đầu tiên được chuyển đổi thành int(một quy tắc kỳ lạ). Vì vậy, tôi thực sự phải thực hiện trình diễn với 32-bit (và sau đó nó mở rộng lên 64 bit, 128 bit, ...).
Matthieu M.

2
Vì bạn không thể đánh giá tất cả (4294967296 - 1) * (4294967296 - 1) kết quả có thể xảy ra, bạn giảm bằng cách nào đó? Tôi theo ý kiến ​​của tôi MAX nên là (4294967296 - 1) nếu bạn đi theo cách đó nhưng nó sẽ không bao giờ kết thúc trong suốt cuộc đời của chúng ta như bạn đã nói ... vì vậy, sau tất cả chúng ta không thể cho thấy sự bình đẳng trong một thử nghiệm, ít nhất là không phải trong một thử nghiệm như bạn diễn tả.
Willi Mentzel

1
Thử nghiệm điều này trên việc triển khai bổ sung của one 2 không chứng minh rằng nó có khả năng di động đối với cường độ ký hiệu hoặc phần bổ sung của một người với độ rộng loại Deathstation 9000. ví dụ: một loại không dấu hẹp có thể thăng cấp thành 17-bit intcó thể đại diện cho mọi thứ có thể uint16_t, nhưng a+bcó thể tràn ở đâu . Đó chỉ là một vấn đề đối với các loại không dấu hẹp hơn int; C đòi hỏi unsignedloại là các số nguyên nhị phân, do đó bao quanh xảy ra modulo một sức mạnh của 2
Peter Cordes

1
Đồng ý về việc C quá di động không tốt cho chính nó. Sẽ thực sự tuyệt vời nếu họ chuẩn hóa phần bổ sung của 2, dịch chuyển phải số học cho có dấu và một cách để thực hiện số học có dấu với ngữ nghĩa gói thay vì ngữ nghĩa hành vi không xác định, đối với những trường hợp bạn muốn gói. Sau đó, C một lần nữa có thể hữu ích như một trình lắp ráp di động, thay vì một bãi mìn nhờ các trình biên dịch tối ưu hóa hiện đại khiến việc để lại bất kỳ hành vi không xác định nào không an toàn (ít nhất là đối với nền tảng mục tiêu của bạn. Hành vi không xác định chỉ trên triển khai Deathstation 9000 là được, như bạn chỉ ra).
Peter Cordes,

4

Câu trả lời nhanh là: cả hai biểu thức đều tương đương

  • ablà số nguyên không dấu 32-bit, nên kết quả giống nhau ngay cả trong trường hợp tràn. số học không dấu đảm bảo điều này: một kết quả không thể được biểu diễn bằng kiểu số nguyên không dấu kết quả được giảm mô-đun thành số lớn hơn một giá trị lớn nhất mà kiểu kết quả có thể biểu diễn.

Câu trả lời dài là: không có nền tảng nào được biết đến mà các biểu thức này sẽ khác nhau, nhưng Tiêu chuẩn không đảm bảo điều đó, vì các quy tắc thăng hạng tích phân.

  • Nếu kiểu ab(số nguyên 32 bit không dấu) có thứ hạng cao hơn int, thì phép tính được thực hiện dưới dạng không dấu, modulo 2 32 , và nó mang lại cùng một kết quả được xác định cho cả hai biểu thức cho tất cả các giá trị của ab.

  • Ngược lại, Nếu kiểu của abnhỏ hơn int, cả hai đều được thăng cấp intvà tính toán được thực hiện bằng số học có dấu, trong đó tràn gọi hành vi không xác định.

    • Nếu intcó ít nhất 33 bit giá trị, cả hai biểu thức trên đều không thể làm tràn, vì vậy kết quả được xác định hoàn hảo và có cùng giá trị cho cả hai biểu thức.

    • Nếu intcó chính xác 32 bit giá trị, thì phép tính có thể làm tràn cho cả hai biểu thức, ví dụ như các giá trị a=0xFFFFFFFFb=1sẽ gây ra tràn trong cả hai biểu thức. Để tránh điều này, bạn cần phải viết ((a & 255) + (b & 255)) & 255.

  • Tin tốt là không có nền tảng nào như vậy 1 .


1 Chính xác hơn, không có nền tảng thực nào như vậy tồn tại, nhưng người ta có thể định cấu hình DS9K để thể hiện hành vi như vậy và vẫn tuân thủ Tiêu chuẩn C.


3
Tiểu tin thứ 2 của bạn yêu cầu (1) anhỏ hơn int(2) intcó 32 bit giá trị (3) a=0xFFFFFFFF. Những điều đó không thể là sự thật.
Barry

1
@Barry: Một trường hợp có vẻ đáp ứng các yêu cầu là 33-bit int, trong đó có 32 bit giá trị và một bit dấu.
Ben Voigt

2

Giả sử giống hệt nhau không có tràn . Không có phiên bản nào thực sự miễn nhiễm với tràn nhưng phiên bản kép và phiên bản có khả năng chống lại nó nhiều hơn. Tôi không biết về một hệ thống mà lỗi tràn trong trường hợp này là một vấn đề nhưng tôi có thể thấy tác giả thực hiện điều này trong trường hợp có.


1
OP đã chỉ định: (a và b là các số nguyên không dấu 32 bit) . Trừ khi intrộng 33 bit, kết quả là như nhau ngay cả trong trường hợp tràn. số học không dấu đảm bảo điều này: một kết quả không thể được biểu diễn bằng kiểu số nguyên không dấu kết quả được giảm theo mô đun số lớn hơn một giá trị lớn nhất mà kiểu kết quả có thể biểu diễn.
chqrlie

2

Có, bạn có thể chứng minh điều đó bằng số học, nhưng có một câu trả lời trực quan hơn.

Khi thêm vào, mỗi bit chỉ ảnh hưởng đến những thứ quan trọng hơn chính nó; không bao giờ những ít quan trọng hơn.

Do đó, bất cứ điều gì bạn làm với các bit cao hơn trước khi thêm vào sẽ không thay đổi kết quả, miễn là bạn chỉ giữ lại các bit ít quan trọng hơn so với bit thấp nhất được sửa đổi.


0

Bằng chứng là tầm thường và để lại như một bài tập cho người đọc

Nhưng để thực sự hợp pháp hóa điều này như một câu trả lời, dòng mã đầu tiên của bạn nói rằng hãy lấy 8 bit cuối cùng của b** (tất cả các bit cao hơn bđược đặt thành 0) và thêm điều này vào avà sau đó chỉ lấy 8 bit cuối cùng của cài đặt kết quả cao hơn bit đến không.

Dòng thứ hai cho biết thêm abvà lấy 8 bit cuối cùng với tất cả các bit cao hơn bằng không.

Chỉ 8 bit cuối cùng là có ý nghĩa trong kết quả. Do đó, chỉ 8 bit cuối cùng là quan trọng trong (các) đầu vào.

** 8 bit cuối cùng = 8 LSB

Cũng cần lưu ý rằng đầu ra sẽ tương đương với

char a = something;
char b = something;
return (unsigned int)(a + b);

Như trên, chỉ có 8 LSB là quan trọng, nhưng kết quả là một unsigned intvới tất cả các bit khác bằng không. Ý a + bchí tràn ra, tạo ra kết quả như mong đợi.


Không, nó sẽ không. Phép toán Char xảy ra khi int và char có thể được ký.
Antti Haapala
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.