2017-11-29 15 views
12

Theo lời khuyên của người dùng SO đại diện, gần đây tôi đã bắt đầu biên dịch với cờ -Wconversion trên codebase của tôi. Điều này đã tạo ra khá một vài cảnh báo, một số trong đó là hợp pháp (không cần thiết thêm signedunsigned loại, ví dụ), nhưng cũng có một số scratchers đầu, chứng minh dưới đây:g ++: chuyển đổi thành uint16_t từ int có thể thay đổi giá trị

#include <cstdint> 

int main() 
{ 
    uint16_t a = 4; 
    uint16_t b = 5; 

    b += a; 

    return 0; 
} 

Khi tôi biên dịch với g++ -Wconversion -std=c++11 -O0 myFile.cpp, tôi nhận được

warning: conversion to 'uint16_t {aka short unsigned int}' from 'int' may alter its value [-Wconversion] 
    b += a; 
    ^

tôi đã đọc kỹ một số câu hỏi tương tự trên SO (đối phó với |<< nhà khai thác), lấy một cái nhìn here, và đã đọc Khuyến mãi Numeric và Numeric Chuyển đổi phần here. Hiểu biết của tôi là, để thực hiện phép toán, ab được thăng cấp thành int (vì đó là loại đầu tiên có thể phù hợp với toàn bộ dải giá trị uint16_t), kết quả được viết lại, ngoại trừ kết quả của toán là int và viết lại là uint16_t sẽ tạo cảnh báo. Sự đồng thuận của các câu hỏi khác về cơ bản là bỏ đi cảnh báo, và cách duy nhất tôi đã tìm ra cách để làm điều đó là b = (uint16_t)(b + a); (hoặc tương đương b = static_cast<uint16_t>(b + a);).

Không muốn câu hỏi này để có được quá rộng, nhưng giả sử hiểu biết của tôi về chương trình khuyến mãi số nguyên là đúng ...

  1. cách tốt nhất để xử lý này di chuyển về phía trước là gì? Tôi có nên tránh thực hiện toán học trên các loại hẹp hơn int không? Nó có vẻ khá lạ với tôi rằng tôi phải đúc một kết quả số học đó là cùng loại như tất cả các toán hạng (đoán tôi mong đợi trình biên dịch để nhận ra rằng và ngăn chặn các cảnh báo). Trong lịch sử, tôi đã thích sử dụng không có nhiều bit hơn tôi cần, và chỉ để cho trình biên dịch xử lý các chương trình khuyến mãi/chuyển đổi/padding khi cần thiết.
  2. Bất cứ ai cũng sử dụng cờ -Wconversion thường xuyên? Chỉ sau một vài ngày sử dụng nó bản thân mình, tôi bắt đầu nghĩ rằng trường hợp sử dụng tốt nhất của nó là để bật nó lên, nhìn vào những gì nó phàn nàn về, sửa chữa các khiếu nại hợp pháp, sau đó biến nó trở lại. Hoặc có lẽ định nghĩa của tôi về "khiếu nại hợp pháp" cần điều chỉnh lại. Thay thế tất cả các toán tử += của tôi với các phôi được đánh vần có vẻ như phiền toái hơn bất kỳ thứ gì.

Tôi cũng muốn gắn thẻ này là c, vì mã tương đương c được biên dịch với gcc -Wconversion -std=c11 -O0 myFile.c cũng đưa ra cảnh báo tương tự. Nhưng như vậy, tôi đang sử dụng g++ phiên bản 5.3.1 trên một hộp Fedora 23 x86_64. Xin vui lòng chỉ cho tôi để các dupe nếu tôi đã bỏ lỡ nó; nếu câu trả lời/lời khuyên duy nhất ở đây là bỏ đi cảnh báo, thì đây là một bản dupe.

+2

Nó không hoàn toàn là một sự lừa đảo, nhưng [câu trả lời này] (https://stackoverflow.com/a/39061103/1270789) xác nhận sự nghi ngờ của bạn. Tuy nhiên, cách xử lý cảnh báo '-Wconversion' chưa được trả lời, nhưng đáng để trả lời ở đây. (Và [C# thậm chí còn khó hiểu hơn] (https://stackoverflow.com/q/4343624/1270789)). –

+2

xử lý tiếng kêu '-Wconversion' khác nhau, nó không cảnh báo cho trường hợp này. Tôi sử dụng công tắc này được bật tất cả thời gian (tôi không tắt, như bạn nói trong 2.) và tôi luôn khắc phục sự cố. Nhưng tôi hiếm khi sử dụng các loại ngắn hơn cho arithmetics. Đơn giản là không có lý do gì để sử dụng chúng. – geza

+1

"Theo lời khuyên của một người dùng SO đại diện" - tốt, lời khuyên của tôi sẽ không sử dụng lá cờ đó bởi vì nó cho quá nhiều xác thực sai! Thành thật mà nói, tôi xem xét trường hợp trong câu hỏi của bạn là một lỗi trình biên dịch. –

Trả lời

3

Tôi nghĩ rằng điều này có thể được coi là thiếu sót của gcc.

Như mã này không tạo ra bất kỳ cảnh báo:

int a = ..., b = ...; 

a += b; 

Mã này không nên tạo ra một trong hai, bởi vì ngữ nghĩa họ đều giống nhau (hai số cùng loại được thêm vào, và kết quả được đưa vào một cùng kiểu biến):

short a = ..., b = ...; 

a += b; 

Nhưng GCC tạo ra một cảnh báo, bởi vì như bạn nói, short 's được thăng int' s.Nhưng phiên bản short không nguy hiểm hơn, theo nghĩa là nếu tràn bổ sung, thì hành vi được xác định thực hiện cho cả hai trường hợp (hoặc nếu số không dấu được sử dụng, thì cắt ngắn có thể xảy ra trong cả hai trường hợp).

Clang xử lý trường hợp này thông minh hơn và không cảnh báo cho trường hợp này. Tôi nghĩ rằng đó là bởi vì nó thực sự theo dõi các bit có thể chiều rộng (hoặc có thể phạm vi?) Của kết quả. Vì vậy, ví dụ, điều này cảnh báo:

int a = ...; 
short b = a; 

Nhưng điều này không (nhưng GCC cảnh báo cho việc này):

int a = ...; 
short b = a&0xf; // there is a conversion here, but clang knows that only 4 bits are used, so it doesn't warn 

Vì vậy, cho đến khi GCC sẽ có một thông minh hơn -Wconversion, lựa chọn của bạn là:

  1. không sử dụng -Wconversion
  2. sửa chữa tất cả những lời cảnh báo nó in
  3. sử dụng tiếng kêu thay thế (có thể cho GCC: tắt cảnh báo này; và cho kêu vang: bật tính năng này)

Nhưng đừng nín thở cho đến khi nó cố định, có một bug về điều này, mở cửa vào năm 2009.

Một lưu ý:

Về mặt lịch sử , Tôi đã thích sử dụng không có nhiều bit hơn tôi cần, và chỉ để cho trình biên dịch xử lý các chương trình khuyến mãi/chuyển đổi/padding khi cần thiết.

Nếu bạn sử dụng các loại lưu trữ ngắn hơn thì tốt. Nhưng thông thường, không có lý do gì để sử dụng các loại ngắn hơn int cho số học. Nó không cho phép tăng tốc (thậm chí, nó có thể chậm hơn, vì các mặt nạ không cần thiết).

4

Cách tốt nhất để xử lý điều này là gì?

-Wno-conversion 

Hoặc chỉ để không được chỉ định. Đây chỉ là một ý kiến, mặc dù. Theo kinh nghiệm của tôi, nhu cầu về số học số nguyên hẹp có xu hướng khá hiếm, vì vậy bạn vẫn có thể giữ nó cho dự án và vô hiệu hóa trong một vài trường hợp cảnh báo vô dụng này xảy ra. Tuy nhiên, điều này có thể phụ thuộc rất nhiều vào loại dự án của bạn, vì vậy trải nghiệm của bạn có thể thay đổi.

Tôi có nên tránh thực hiện toán học trên các loại hẹp hơn int không?

Thường có; trừ khi bạn có một lý do cụ thể để sử dụng chúng. "Tôi không cần thêm các bit" không phải là một lý do đủ cụ thể theo ý kiến ​​của tôi. Toán hạng số học được thăng lên int dù sao và thường nhanh hơn và ít bị lỗi hơn khi sử dụng int.

Chỉ sau một vài ngày sử dụng bản thân, tôi bắt đầu nghĩ trường hợp sử dụng tốt nhất là bật nó lên, nhìn vào những gì nó than phiền, sửa các khiếu nại hợp pháp, rồi tắt nó đi .

Đây là khá thường xuyên một cách tiếp cận hữu ích để cờ cảnh báo được bao gồm trong không -Wall cũng không -Wextra như những người thân với -Wsuggest- tiền tố. Có một lý do tại sao họ không được bao gồm trong "tất cả các cảnh báo".

Các vấn đề liên quan