用显式转换替换隐式转换是否有任何副作用?

时间:2015-03-27 11:48:38

标签: c casting implicit-conversion

显式转换是否更好,而不仅仅是使用隐式转换?

例如,我有一个枚举...

/*This enum represents the various encryption types for wifi. For wifi capable devices, a bitwise & result of all supported encryption types should be returned.*/
typedef enum wifi_encryptionType {
    /*Unknown encryption - default value, and for if wifi standard is ever expanded.*/
    WIFIENCTYPE_UNKNOWN = 0,

    /*No encryption - an open network.*/
    WIFIENCTYPE_NONE = 1,

    /*WEP encryption - all widths.*/
    WIFIENCTYPE_WEP = 2,

    /*WPA 1 with a preshared key using Temporal Key Integrity Protocol.*/
    WIFIENCTYPE_WPA_PSK_TKIP = 4,

    /*WPA 1 with a preshared key using Advanced Encryption Standard via CCMP. */
    WIFIENCTYPE_WPA_PSK_AES = 8,

    /*WPA 2 with a preshared key using Temporal Key Integrity Protocol.*/
    WIFIENCTYPE_WPA2_PSK_TKIP = 16,

    /*WPA 2 with a preshared key using Advanced Encryption Standard via CCMP.*/
    WIFIENCTYPE_WPA2_PSK_AES = 32

} wifi_encryptionType;

我在结构中使用。

typedef struct {
    char ssid[32];
    wifi_encryptionType encryption;
    wifi_mode mode;
} WifiNetwork;

我使用该结构字段的值作为函数调用的参数...

read_uint8(readBuffer, &network.encryption);
//read_uint8 takes a struct pointer containing some buffer info, and a uint8_t pointer.

我收到警告。

warning: passing argument 2 of 'read_uint8' from incompatible pointer type
expected 'uint8_t *' but argument is of type 'enum wifi_encryptionType *'

我得到警告意味着什么。 "请注意,阅读uint8_t并将其放入wifi_encryptionType字段可以在其中放置不会映射到您声明的任何值的值。"

现在可以隐式进行类型转换。

让它成为一个明确的演员阵容会更好吗?制作演员表是否有任何好处 - 或者有任何缺点?

2 个答案:

答案 0 :(得分:1)

这种情况下的警告并不仅仅是编译器的挑剔。这可能会破裂。

原因是enum类型的大小可能与uint8_t不同。 C11标准仅保证(第6.7.2.2节)

  

每个枚举类型应与char兼容,有符号整数类型,   或无符号整数类型。

如果您感到不幸,enum的表示方式与例如int相同int,然后您有效地将指针传递给int的初始字节。在大端系统上,该字节与int*的值不同,即使该值适合。

另一个问题(可能不适用于此处)是严格别名,这意味着允许编译器假设相同的数据不能作为两个不同的方式访问类型。一个示例是将float*int*指向同一位置,通过float*写入该位置,然后通过int*从中读取。严格的别名规则允许代码优化,因为编译器可以假设通过float*写入不会弄乱uint8_t指向的值(因此必须将其重新加载到例如注册。)

严格别名可能不适用于此的原因是unsigned char在实践中几乎肯定是char*,编译器为此做出异常。 unsigned char*(或memcpy())可用于访问任何类型对象的内存。如果不允许这样做,那么就没有任何安全的方法可以做到" raw"例如,根据需要的字节操作{{1}}。

答案 1 :(得分:0)

enum(最有可能)是int

因此,您传递int的地址,其中uint8_t的地址是预期的。

编译器告诉你:

warning: passing argument 2 of 'read_uint8' from incompatible pointer type expected 'uint8_t *' but argument is of type 'enum wifi_encryptionType *'

这样做会导致灾难。

要解决此问题,请使用临时中间变量:

{
  uint8_t tmp = network.encryption;
  read_uint8(readBuffer, &tmp);
  network.encryption = tmp;
}