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

Does replacing implicit conversion with explicit casting have any side-effects?

显式转换比隐式转换更好吗?

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

/*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 *'

我明白警告的意思了。 "Be aware that reading a uint8_t and putting it into a wifi_encryptionType field can place values in there that do not map to any of the values you have declared."

类型转换现在隐式完成。

让它显式转换更好吗?显式转换是否有任何好处或任何缺点?

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;
}

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

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

Each enumerated type shall be compatible with char, a signed integer type, or an unsigned integer type.

如果你运气不好,enum 具有与例如相同的表示形式int,那么您将有效地传递一个指向 int 的初始字节的指针。在大端系统上,该字节的值不会与 int 相同,即使该值适合。

另一个问题(虽然可能不会在这里应用)是严格别名,这意味着允许编译器假设相同的数据不作为两个访问不同种类。一个例子是让 int*float* 指向相同的位置,通过 int* 写入该位置,然后通过 float* 从中读取。严格的别名规则允许代码优化,因为编译器可以假设通过 int* 写入不会弄乱 float* 指向的值(因此它必须重新加载到寄存器中例如)。

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