Làm cách nào để nén mã cho nhiều Flash và RAM? [đóng cửa]


14

Tôi đã làm việc để phát triển một tính năng trên một sản phẩm cụ thể của chúng tôi. Đã có một yêu cầu chuyển tính năng tương tự sang một sản phẩm khác. Sản phẩm này dựa trên bộ vi điều khiển M16C, theo truyền thống có 64K Flash và 2k RAM.

Nó là một sản phẩm trưởng thành và do đó, chỉ còn lại 132 Byte Flash và 2 byte RAM.

Để chuyển tính năng được yêu cầu (bản thân tính năng đã được tối ưu hóa), tôi cần 1400 byte Flash và ~ 200 Byte RAM.

Có ai có bất kỳ đề xuất nào về cách lấy các Byte này bằng cách nén mã không? Những điều cụ thể nào tôi tìm kiếm khi tôi đang cố gắng nén mã làm việc hiện có?

Bất kỳ ý tưởng sẽ thực sự được đánh giá cao.

Cảm ơn.


1
Cảm ơn mọi người vì những gợi ý. Tôi sẽ cập nhật cho bạn về tiến trình của tôi và liệt kê các bước đã hoạt động và những bước không hiệu quả.
IntelliChick

Ok, đây là những điều tôi đã thử làm việc: Chuyển lên các phiên bản trình biên dịch. Việc tối ưu hóa đã được cải thiện mạnh mẽ, mang lại cho tôi khoảng 2K Flash. Đi qua các tệp danh sách để kiểm tra chức năng dự phòng và không sử dụng (được kế thừa vì cơ sở mã chung) cho sản phẩm cụ thể và nhận được thêm một số Flash.
IntelliChick

Đối với RAM, tôi đã làm như sau: Đi qua tệp bản đồ, để kiểm tra các chức năng / mô-đun đang sử dụng nhiều RAM nhất. Tôi đã tìm thấy một chức năng thực sự nặng nề (12 kênh, mỗi kênh có một lượng bộ nhớ được phân bổ cố định), mã kế thừa, hiểu những gì nó đang cố gắng đạt được và tối ưu hóa việc sử dụng RAM, bằng cách chia sẻ thông tin giữa các kênh phổ biến. Điều này đã cho tôi ~ 200 Byte mà tôi cần.
IntelliChick

Nếu bạn có tệp ascii, bạn có thể sử dụng nén 8 đến 7 bit. Tiết kiệm cho bạn 12,5%. Sử dụng một tệp zip sẽ mất nhiều mã hơn để nén và giải nén nó hơn là chỉ để nó được.
Sparky256

Câu trả lời:


18

Bạn có một vài lựa chọn: đầu tiên là tìm kiếm mã dự phòng và chuyển nó sang một cuộc gọi duy nhất để thoát khỏi sự trùng lặp; thứ hai là loại bỏ chức năng.

Hãy nhìn kỹ vào tệp .map của bạn và xem liệu có các chức năng mà bạn có thể loại bỏ hoặc viết lại không. Cũng đảm bảo rằng các cuộc gọi thư viện đang được sử dụng là thực sự cần thiết.

Một số thứ như phép chia và phép nhân có thể mang lại rất nhiều mã nhưng sử dụng ca và sử dụng hằng số tốt hơn có thể làm cho mã nhỏ hơn. Cũng có một cái nhìn vào những thứ như hằng chuỗi và printfs. Ví dụ, mỗi cái printfsẽ ăn hết rom của bạn nhưng bạn có thể có một vài chuỗi định dạng được chia sẻ thay vì lặp đi lặp lại chuỗi đó liên tục.

Đối với bộ nhớ, xem bạn có thể thoát khỏi toàn cầu và sử dụng ô tô trong một chức năng thay thế. Cũng nên tránh càng nhiều biến số trong chức năng chính càng tốt, vì những điều này ăn hết bộ nhớ giống như toàn cầu.


1
Cảm ơn các đề xuất, tôi chắc chắn có thể thử hầu hết trong số chúng, ngoại trừ một cho các hằng chuỗi. Nó hoàn toàn là một thiết bị nhúng, không có UI và do đó không có lệnh gọi printf () trong mã. Hy vọng rằng những đề xuất đó sẽ giúp tôi vượt qua để nhận được 1400 Byte Flash / 200 byte RAM mà tôi cần.
IntelliChick

1
@IntelliChick bạn sẽ ngạc nhiên khi có nhiều người sử dụng printf () bên trong thiết bị nhúng để in để gỡ lỗi hoặc gửi đến thiết bị ngoại vi. Có vẻ như bạn biết rõ hơn về điều này, nhưng nếu bất cứ ai đã viết mã về dự án trước bạn, sẽ không hại gì khi kiểm tra nó.
Kellenjb

5
Và chỉ để mở rộng nhận xét trước đây của tôi, bạn cũng sẽ ngạc nhiên khi có nhiều người thêm các câu lệnh gỡ lỗi, nhưng không bao giờ xóa chúng. Ngay cả những người làm #ifdefs đôi khi vẫn lười biếng.
Kellenjb

1
Thật sự cảm ơn! Tôi đã thừa hưởng codebase này, vì vậy tôi chắc chắn sẽ xem xét chúng. Tôi sẽ thông báo cho các bạn về tiến trình và cố gắng theo dõi xem tôi đã đạt được bao nhiêu byte bộ nhớ hoặc Flash bằng cách làm gì, giống như một tài liệu tham khảo cho bất kỳ ai khác có thể cần làm điều này trong tương lai.
IntelliChick

Chỉ cần một câu hỏi về điều này - những gì về chức năng lồng nhau gọi bước nhảy từ lớp này sang lớp khác. Bao nhiêu chi phí mà thêm? Có tốt hơn để giữ tính mô đun bằng cách có nhiều lệnh gọi hàm hoặc giảm các lệnh gọi hàm và lưu một số byte. Và điều đó có ý nghĩa?
IntelliChick

8

Luôn luôn đáng để xem đầu ra tệp liệt kê (trình biên dịch) để tìm kiếm những thứ mà trình biên dịch cụ thể của bạn đặc biệt tệ.

Ví dụ, bạn có thể thấy rằng các biến cục bộ rất đắt tiền và nếu ứng dụng đủ đơn giản để có giá trị rủi ro, việc chuyển một vài bộ đếm vòng lặp thành các biến tĩnh có thể tiết kiệm rất nhiều mã.

Hoặc lập chỉ mục mảng có thể rất tốn kém nhưng hoạt động con trỏ rẻ hơn nhiều. Hoặc ngược lại.

Nhưng nhìn vào ngôn ngữ lắp ráp là bước đầu tiên.


3
Điều rất quan trọng là bạn biết trình biên dịch của bạn làm gì. Bạn sẽ thấy những gì phân chia trên trình biên dịch của tôi. Nó làm cho em bé khóc (bao gồm cả bản thân tôi).
Kortuk

8

Tối ưu hóa trình biên dịch, ví dụ, -Ostrong GCC mang lại sự cân bằng tốt nhất giữa tốc độ và kích thước mã. Tránh -O3, vì nó có thể làm tăng kích thước mã.


3
Nếu bạn làm điều này, bạn sẽ cần kiểm tra lại MỌI THỨ! Tối ưu hóa có thể khiến mã làm việc không hoạt động do các giả định mới mà trình biên dịch đưa ra.
Robert

@Robert, điều đó chỉ đúng nếu bạn sử dụng các câu lệnh không xác định: ví dụ a = a ++ sẽ biên dịch khác nhau trong -O0 và -O3.
Thomas O

5
@Thomas không đúng. Nếu bạn có một vòng lặp for để trì hoãn chu kỳ đồng hồ, nhiều trình tối ưu hóa sẽ nhận ra bạn không làm gì trong đó và loại bỏ nó. Đây chỉ là 1 ví dụ.
Kellenjb

1
@thomas O, Bạn cũng cần đảm bảo rằng bạn cẩn thận về các định nghĩa hàm dễ bay hơi. Tối ưu hóa sẽ thổi bay những người nghĩ rằng họ biết rõ về C nhưng không hiểu được sự phức tạp của các hoạt động nguyên tử.
Kortuk

1
Tất cả những điểm tốt. Các hàm / biến dễ bay hơi, theo định nghĩa, KHÔNG được tối ưu hóa. Bất kỳ trình tối ưu hóa nào thực hiện tối ưu hóa như vậy (bao gồm cả thời gian gọi và nội tuyến) đều bị hỏng.
Thomas O

8

Đối với RAM, hãy kiểm tra phạm vi của tất cả các biến của bạn - bạn có đang sử dụng ints nơi bạn có thể sử dụng char không? Là bộ đệm lớn hơn họ cần phải được?

Việc ép mã rất phụ thuộc vào ứng dụng và kiểu mã hóa. Số tiền còn lại của bạn cho thấy rằng có thể mã đã biến mất mặc dù có một số vắt, điều đó có nghĩa là có rất ít phải có.

Ngoài ra, hãy nhìn kỹ vào chức năng tổng thể - có thứ gì đó không thực sự được sử dụng và có thể bị loại bỏ?


8

Nếu đó là một dự án cũ nhưng trình biên dịch đã được phát triển kể từ đó, thì có thể là một trình biên dịch gần đây hơn có thể tạo ra mã nhỏ hơn


Cảm ơn Mike! Tôi đã thử điều này trong quá khứ và không gian đã đạt được đã được sử dụng! :) Đã chuyển từ trình biên dịch IAR C 3.21d lên 3.40.
IntelliChick

1
Tôi đã chuyển lên một phiên bản nữa và đã tìm được thêm một số Flash để phù hợp với tính năng này. Tôi thực sự đang vật lộn với RAM, mặc dù vậy, điều đó vẫn không thay đổi. :(
IntelliChick

7

Luôn luôn đáng để kiểm tra hướng dẫn trình biên dịch của bạn để biết các tùy chọn để tối ưu hóa không gian.

Đối với gcc -ffunction-sections-fdata-sectionsvới --gc-sectionscờ liên kết là tốt để tước mã chết.

Dưới đây là một số lời khuyên tuyệt vời khác (hướng tới AVR)


Điều này thực sự làm việc? Các tài liệu nói "Khi bạn chỉ định các tùy chọn này, trình biên dịch và trình liên kết sẽ tạo các đối tượng lớn hơn và các tệp thực thi và cũng sẽ chậm hơn." Tôi hiểu rằng việc có các phần riêng biệt có ý nghĩa đối với vi mô với các phần Flash và RAM - Có phải tuyên bố này trong tài liệu không áp dụng cho vi điều khiển không?
Kevin Vermeer

Kinh nghiệm của tôi là nó hoạt động tốt cho AVR
Toby Jaffey

1
Điều này không hoạt động tốt trong hầu hết các trình biên dịch tôi đã sử dụng. Nó giống như sử dụng từ khóa đăng ký. Bạn có thể nói với trình biên dịch rằng một biến đi vào một thanh ghi, nhưng một trình tối ưu hóa tốt sẽ làm điều này tốt hơn nhiều so với con người (lập luận như một số có thể, nó được coi là không thể chấp nhận để làm điều này trong thực tế).
Kortuk

1
Khi bạn bắt đầu gán vị trí, bạn buộc trình biên dịch đặt mọi thứ vào một số vị trí nhất định, rất quan trọng đối với mã trình tải khởi động nâng cao, nhưng thật tệ khi xử lý trình tối ưu hóa, khi bạn đưa ra quyết định cho nó, bạn sẽ bỏ đi một bước tối ưu hóa Có thể làm. Trong một số trình biên dịch, họ thiết kế nó để có các phần cho mã được sử dụng cho mục đích gì, đây là trường hợp thông báo cho trình biên dịch thêm thông tin để hiểu cách sử dụng của bạn, điều này sẽ giúp ích. Nếu trình biên dịch không đề xuất nó, đừng làm điều đó.
Kortuk

6

Bạn có thể kiểm tra lượng không gian ngăn xếp và không gian đống được phân bổ. Bạn có thể lấy lại một lượng RAM đáng kể nếu một hoặc cả hai thứ này được phân bổ quá mức.

Tôi đoán là cho một dự án mà phù hợp vào 2k RAM để bắt đầu với không có cấp phát bộ nhớ động (sử dụng malloc, callocvv). Nếu đây là trường hợp bạn có thể thoát khỏi heap của mình hoàn toàn giả sử tác giả ban đầu để lại một số RAM được phân bổ cho heap.

Bạn phải rất cẩn thận giảm kích thước ngăn xếp vì điều này có thể gây ra các lỗi rất khó tìm. Có thể hữu ích khi bắt đầu bằng cách khởi tạo toàn bộ không gian ngăn xếp thành một giá trị đã biết (một cái gì đó không phải là 0x00 hoặc 0xff vì các giá trị này thường xảy ra) sau đó chạy hệ thống trong một thời gian để xem có bao nhiêu không gian ngăn xếp không được sử dụng.


Đây là những lựa chọn rất tốt. Tôi sẽ lưu ý rằng bạn không bao giờ nên sử dụng malloc trong một hệ thống nhúng.
Kortuk

1
@Kortuk Điều đó phụ thuộc vào định nghĩa của bạn về nhúng và nhiệm vụ được thực hiện
Toby Jaffey

1
@joby, Vâng, tôi hiểu điều đó. Trong một hệ thống có 0 khởi động lại và không có HĐH như linux, Malloc có thể rất rất tệ.
Kortuk

Không có phân bổ bộ nhớ động, không có nơi malloc, calloc đang được sử dụng. Tôi cũng đã kiểm tra phân bổ heap và nó đã được đặt thành 0 rồi, vì vậy không có phân bổ heap. Kích thước ngăn xếp được phân bổ hiện tại là 254 Byte và kích thước ngăn xếp ngắt trong 128 byte.
IntelliChick

5

Mã của bạn có sử dụng toán học dấu phẩy động không? Bạn có thể chỉ thực hiện lại các thuật toán của mình bằng toán học số nguyên và loại bỏ các chi phí sử dụng thư viện dấu phẩy động C. Ví dụ, trong một số ứng dụng, các hàm như sin, log, exp có thể được thay thế bằng các xấp xỉ đa thức nguyên.

Mã của bạn có sử dụng các bảng tra cứu lớn cho bất kỳ thuật toán nào không, chẳng hạn như tính toán CRC? Bạn có thể thử thay thế một phiên bản khác của thuật toán tính toán các giá trị đang hoạt động, thay vì sử dụng các bảng tra cứu. Thông báo trước là thuật toán nhỏ hơn rất có thể chậm hơn, vì vậy hãy đảm bảo bạn có đủ chu kỳ CPU.

Mã của bạn có số lượng lớn dữ liệu không đổi, chẳng hạn như bảng chuỗi, trang HTML hoặc đồ họa pixel (biểu tượng) không? Nếu nó đủ lớn (giả sử 10 kB), có thể đáng để thực hiện một sơ đồ nén rất đơn giản để thu nhỏ dữ liệu và giải nén nó ngay lập tức khi cần.


Có 2 bảng tra cứu nhỏ, không có bảng nào sẽ lên tới 10K. Và không có toán học dấu phẩy động nào được sử dụng. :( Cảm ơn những lời đề nghị mặc dù. Chúng rất tốt.
IntelliChick

2

Bạn có thể cố gắng sắp xếp lại để mã hóa rất nhiều, để một phong cách nhỏ gọn hơn. Nó phụ thuộc rất nhiều vào những gì mã đang làm. Điều quan trọng là tìm ra những thứ tương tự và thực hiện lại chúng theo nghĩa của nhau. Một thái cực sẽ là sử dụng một ngôn ngữ cấp cao hơn, như Forth, với ngôn ngữ đó có thể dễ dàng đạt được mật độ mã cao hơn so với trong C hoặc trình biên dịch.

Đây là Forth cho M16C .


2

Đặt mức tối ưu hóa của trình biên dịch. Nhiều IDE có các cài đặt cho phép tối ưu hóa kích thước mã với chi phí thời gian biên dịch (hoặc thậm chí có thể xử lý thời gian trong một số trường hợp). Họ có thể thực hiện nén mã bằng cách chạy lại trình tối ưu hóa của mình một vài lần, tìm kiếm các mẫu có khả năng tối ưu hóa ít phổ biến hơn và một loạt các thủ thuật khác có thể không cần thiết cho quá trình biên dịch ngẫu nhiên / gỡ lỗi. Thông thường, theo mặc định, trình biên dịch được đặt ở mức tối ưu hóa trung bình. Đi sâu vào các cài đặt, bạn sẽ có thể tìm thấy một số thang đo tối ưu hóa dựa trên số nguyên.


1
Hiện được tối ưu hóa đến Tối đa cho Kích thước. :) Nhờ đề nghị mặc dù. :)
IntelliChick

2

Nếu bạn đang sử dụng trình biên dịch cấp chuyên nghiệp như IAR, tôi nghĩ rằng bạn sẽ phải vật lộn để có được bất kỳ khoản tiết kiệm nghiêm trọng nào bằng cách điều chỉnh mã cấp độ nhỏ - bạn sẽ cần phải tìm kiếm nhiều hơn về chức năng hoặc thực hiện chính viết lại các bộ phận một cách hiệu quả hơn. Bạn sẽ cần phải là một lập trình viên thông minh hơn bất kỳ ai đã viết phiên bản gốc ... Đối với RAM, bạn cần phải xem xét kỹ về cách sử dụng nó hiện tại, và xem liệu có phạm vi nào cho việc sử dụng cùng loại RAM không những thứ khác nhau ở những thời điểm khác nhau (công đoàn có ích cho việc này). Kích thước heap và stack mặc định của IAR trong các ARM / AVR mà tôi có xu hướng quá hào phóng, vì vậy đây sẽ là điều đầu tiên cần xem xét.


Cảm ơn Mike. Mã này đã sử dụng các công đoàn ở hầu hết các nơi, nhưng tôi sẽ xem xét một số nơi khác, nơi điều này vẫn có thể giúp đỡ. Tôi cũng sẽ xem xét kích thước ngăn xếp được chọn và xem liệu điều đó có thể được tối ưu hóa không.
IntelliChick

Làm thế nào để tôi biết kích thước Stack nào là phù hợp?
IntelliChick

2

Một cái gì đó khác để kiểm tra - một số trình biên dịch trên một số kiến ​​trúc sao chép các hằng số vào RAM - thường được sử dụng khi truy cập vào các hằng số flash chậm / khó (ví dụ: AVR), ví dụ trình biên dịch AVR của IAR yêu cầu trình định dạng _ _flash không sao chép hằng số vào RAM)


Cảm ơn Mike. Phải tôi đã kiểm tra xem - nó được gọi là tùy chọn 'Hằng có thể ghi' cho trình biên dịch M16C IAR C. Nó sao chép các hằng số từ ROM sang RAM. Tùy chọn này được bỏ chọn cho dự án của tôi. Nhưng một kiểm tra thực sự hợp lệ! Cảm ơn.
IntelliChick

1

Nếu bộ xử lý của bạn không có hỗ trợ phần cứng cho ngăn xếp tham số / cục bộ nhưng trình biên dịch sẽ cố gắng thực hiện ngăn xếp tham số thời gian chạy và nếu mã của bạn không cần phải đăng ký lại, bạn có thể lưu mã không gian bằng cách phân bổ tĩnh các biến tự động. Trong một số trường hợp, điều này phải được thực hiện thủ công; trong các trường hợp khác, chỉ thị trình biên dịch có thể làm điều đó. Phân bổ thủ công hiệu quả sẽ yêu cầu chia sẻ các biến giữa các thói quen. Việc chia sẻ này phải được thực hiện cẩn thận, để đảm bảo rằng không có thói quen nào sử dụng một biến mà một thói quen khác coi là "trong phạm vi", nhưng trong một số trường hợp, lợi ích kích thước mã có thể là đáng kể.

Một số bộ xử lý có các quy ước gọi có thể làm cho một số kiểu truyền tham số hiệu quả hơn các kiểu khác. Ví dụ, trên các bộ điều khiển PIC18, nếu một thường trình có một tham số một byte, thì nó có thể được truyền vào một thanh ghi; nếu cần nhiều hơn thế, tất cả các tham số phải được truyền vào RAM. Nếu một thường trình sẽ lấy hai tham số một byte, thì có thể hiệu quả nhất là "truyền" một tham số trong biến toàn cục, và sau đó chuyển tham số kia thành tham số. Với các thói quen được sử dụng rộng rãi, tiết kiệm có thể tăng lên. Chúng có thể đặc biệt quan trọng nếu tham số được truyền qua toàn cầu là cờ một bit hoặc nếu thông thường sẽ có giá trị 0 hoặc 255 (vì các hướng dẫn đặc biệt tồn tại để lưu 0 hoặc 255 vào RAM).

Trên ARM, việc đặt các biến toàn cục thường được sử dụng cùng nhau vào một cấu trúc có thể làm giảm đáng kể kích thước mã và cải thiện hiệu suất. Nếu A, B, C, D và E là các biến toàn cục riêng biệt, thì mã sử dụng tất cả chúng phải tải địa chỉ của từng biến vào một thanh ghi; nếu không có đủ thanh ghi, có thể cần phải tải lại các địa chỉ đó nhiều lần. Ngược lại, nếu chúng là một phần của cùng cấu trúc toàn cầu MyStuff, thì mã sử dụng MyStuff.A, MyStuff.B, v.v. có thể chỉ cần tải địa chỉ của MyStuff một lần. Chiến thắng lớn.


1

1.Nếu mã của bạn phụ thuộc vào rất nhiều cấu trúc, hãy đảm bảo rằng các thành viên cấu trúc được sắp xếp từ các cấu trúc chiếm ít bộ nhớ nhất.

Ví dụ: "uint32_t uint16_t uint8_t" thay vì "uint16_t uint8_t uint32_t"

Điều này sẽ đảm bảo đệm cấu trúc tối thiểu.

2.Sử dụng const cho các biến khi áp dụng. Điều này sẽ đảm bảo rằng các biến đó sẽ nằm trong ROM và không ngốn RAM


1

Một vài thủ thuật (có lẽ rõ ràng) tôi đã sử dụng thành công trong việc nén mã của một số khách hàng:

  1. Cờ nhỏ gọn vào các trường bit hoặc mặt nạ bit. Điều này có thể có lợi vì thông thường booleans được lưu trữ dưới dạng số nguyên do đó gây lãng phí bộ nhớ. Điều này sẽ tiết kiệm cả RAM và ROM và thường không được trình biên dịch thực hiện.

  2. Tìm kiếm sự dư thừa trong mã và sử dụng các vòng lặp hoặc hàm để thực thi các câu lệnh lặp đi lặp lại.

  3. Tôi cũng đã lưu một số ROM bằng cách thay thế nhiều if(x==enum_entry) <assignment>câu lệnh từ các hằng số bằng một mảng được lập chỉ mục, bằng cách lưu ý rằng các mục enum có thể được sử dụng làm chỉ mục mảng


0

Nếu bạn có thể, hãy sử dụng các hàm nội tuyến hoặc macro trình biên dịch thay vì các hàm nhỏ. Có kích thước và tốc độ vượt trội với việc truyền các đối số và như vậy có thể được khắc phục bằng cách thực hiện chức năng nội tuyến.


1
Bất kỳ trình biên dịch tử tế nào cũng nên thực hiện điều này một cách tự động đối với các funcitons chỉ được gọi một lần.
đồ điện tử

5
Tôi đã tìm thấy nội tuyến thường hữu ích hơn cho việc tối ưu hóa tốc độ và thường với chi phí tăng kích thước.
Craig McQueen

Nội tuyến thường sẽ tăng kích thước mã, ngoại trừ các hàm tầm thường nhưint get_a(struct x) {return x.a;}
Dmitry Grigoryev

0

Thay đổi các biến cục bộ thành cùng kích thước của các thanh ghi CPU của bạn.

Nếu CPU là 32 bit, hãy sử dụng các biến 32 bit ngay cả khi giá trị tối đa sẽ không bao giờ vượt quá 255. Tôi đã sử dụng biến 8 bit, trình biên dịch sẽ thêm mã để che giấu 24 bit trên.

Nơi đầu tiên tôi sẽ xem xét là các biến for-loop.

for( i = 0; i < 100; i++ )

Điều này có vẻ như là một nơi tốt cho một biến 8 bit, nhưng một biến 32 bit có thể tạo ra ít mã hơn.


Điều đó có thể tiết kiệm mã nhưng nó sẽ ăn RAM.
đồ điện tử

Nó sẽ chỉ ăn RAM nếu cuộc gọi chức năng đó nằm trong nhánh dài nhất của dấu vết cuộc gọi. Mặt khác, nó đang sử dụng lại không gian ngăn xếp mà một số chức năng khác đã cần.
Robert

2
Thông thường đúng cung cấp nó là một biến cục bộ. Nếu ngắn về RAM, kích thước của các vars toàn cầu, đặc biệt là mảng, là một nơi tốt để bắt đầu tìm kiếm sự tiết kiệm.
đồ điện tử

1
Another possibility, interestingly, is to replace unsigned variables with signed. If a compiler optimizes an unsigned short to a 32-bit register, it must add code to ensure that its value wraps from 65535 to zero. If, however, the compiler optimizes a signed short to a register, no such code is required. Because there is no guarantee what will happen if a short is incremented beyond 32767, compilers are not required to emit code to deal with that. On at least two ARM compilers I've looked at, signed-short code can be smaller than unsigned-short code for that reason.
supercat
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.