代码之家  ›  专栏  ›  技术社区  ›  Antonio Vázquez Blanco

转换到联合字段的转换产量警告

  •  5
  • Antonio Vázquez Blanco  · 技术社区  · 6 年前

    我使用的是定义以下联合的微芯片微控制器:

    __extension__ typedef struct tagT1CONBITS {
      union {
        struct {
          uint16_t :1;
          uint16_t TCS:1;
          uint16_t TSYNC:1;
          uint16_t :1;
          uint16_t TCKPS:2;
          uint16_t TGATE:1;
          uint16_t :6;
          uint16_t TSIDL:1;
          uint16_t :1;
          uint16_t TON:1;
        };
        struct {
          uint16_t :4;
          uint16_t TCKPS0:1;
          uint16_t TCKPS1:1;
        };
      };
    } T1CONBITS;
    extern volatile T1CONBITS T1CONbits __attribute__((__sfr__));
    

    在我的代码中,我将一个变量定义为一个8位无符号整数,我想将其分配给上面的并集的一个字段。大致如下:

    uint8_t tckps;
    // The value of tckps is calculated here by some magic formula
    tckps = magicformula();
    // We asign the value of tckps to the uC register
    T1CONbits.TCKPS = tckps;
    

    我有 -Wconversion gcc wich中启用的选项会导致以下警告:

    warning: conversion to 'volatile unsigned char:2' from 'uint8_t' may alter its value
    

    我能理解gcc为什么警告我。我当前正在对 tckps 变量,以便我知道数据丢失不会成为问题,但我不知道如何满足gcc转换检查,以便在这种特殊情况下不会警告我。

    如何修复警告?

    提前感谢!

    编辑:添加了工具链信息。

    Microchip Language Tool Shell Version 1.33 (Build date: Oct  9 2017).
    Copyright (c) 2012-2016 Microchip Technology Inc. All rights reserved
    *** Executing: "C:\Program Files (x86)\Microchip\xc16\v1.33\bin\bin/elf-gcc.exe"
       "-v"
    Using built-in specs.
    COLLECT_GCC=C:\Program Files (x86)\Microchip\xc16\v1.33\bin\bin/elf-gcc.exe
    Target: pic30-elf
    Configured with: /home/xc16/release-builds/build_20171009/src/XC_GCC/gcc/configure --build=i386-linux --host=i386-mingw32 --target=pic30-elf --disable-lto --disable-threads --disable-libmudflap --disable-libssp --disable-libstdcxx-pch --disable-hosted-libstdcxx --with-gnu-as --with-gnu-ld --enable-languages=c --disable-nls --disable-libgomp --without-headers --disable-libffi --disable-bootstrap --prefix=/bin --libexecdir=/bin --program-prefix=pic30- --with-libelf=/home/xc16/release-builds/build_20171009/bin/XC_GCC-elf-mingw32-xclm/host-libs/ --with-dwarf2 --with-gmp=/home/xc16/release-builds/build_20171009/bin/XC_GCC-elf-mingw32-xclm/host-libs --with-ppl=/home/xc16/release-builds/build_20171009/bin/XC_GCC-elf-mingw32-xclm/host-libs --with-cloog=/home/xc16/release-builds/build_20171009/bin/XC_GCC-elf-mingw32-xclm/host-libs --with-zlib=/home/xc16/release-builds/build_20171009/bin/XC_GCC-elf-mingw32-xclm/host-libs --with-bugurl=http://www.microchip.com/support --with-host-libstdcxx=-Wl,-Bstatic,-lstdc++,-Bdynamic,-lm
    Thread model: single
    gcc version 4.5.1 (XC16, Microchip v1.33) Build date: Oct  9 2017 (Microchip Technology)
    
    3 回复  |  直到 6 年前
        1
  •  2
  •   Wolfgang    6 年前

    这让met摆脱了警告:

    #include <stdint.h>
    
    typedef struct tagT1CONBITS {
      union {
        struct {
          uint16_t :1;
          uint16_t TCS:1;
          uint16_t TSYNC:1;
          uint16_t :1;
          uint16_t TCKPS:2;
          uint16_t TGATE:1;
          uint16_t :6;
          uint16_t TSIDL:1;
          uint16_t :1;
          uint16_t TON:1;
        };
        struct {
          uint16_t :4;
          uint16_t TCKPS0:1;
          uint16_t TCKPS1:1;
        };
      };
    } T1CONBITS;
    
    volatile T1CONBITS T1CONbits;
    
    uint8_t (*magicformula)(void);
    
    int main(void)
    {
        uint8_t tckps;
        // The value of tckps is calculated here by some magic formula
        tckps = magicformula() ;
        // We asign the value of tckps to the uC register
        T1CONbits.TCKPS = (uint8_t)(tckps & 3); // This fixes the warning
    
        return 0;
    }
    

    我编译它时使用:

    gcc -Wall -Wconversion test2.c
    

    我看到的问题是,编译器无法检查函数边界是否未超出变量的范围。如果您在使用时这样做,编译器可以对此进行检查。

    强制转换是为了避免表达式升级为int时出现警告。

        2
  •  2
  •   Lundin    6 年前

    这是一个 known issue 39170 特别是在使用gcc编译器进行编译时 -Wconversion 。gcc 4.3中存在此问题。x及更高版本。他们可能已经在一些更新的版本中修复了这个问题,但我找不到任何有关它的信息。

    一个可能的棘手问题是将值位屏蔽为位屏蔽,如Wolfgang的回答所示。

        3
  •  1
  •   dbush    6 年前

    您可以有选择地忽略gcc警告 #pragma GCC diagnostic 。以下是如何使用此功能的示例:

    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Wconversion"
        T1CONbits.TCKPS = tckps;
    #pragma GCC diagnostic pop
    

    这个 push pragma存储诊断警告的当前状态。这个 ignored pragma然后告诉编译器从该点开始忽略指定的警告。这个 pop pragma然后恢复先前的诊断状态,因此将打印可能出现转换警告的任何其他位置。

    最终结果是,仅对pragmas之间的特定源行抑制警告。