结构对C和C的定义不同 – 是否安全? PC-Lint发出警告

以下声明在C文件中添加了几个用于编译的运算符.该定义包含在C和C文件中.

PC-Lint报告错误114:标签’Rect’的结构声明不一致但我确信它是安全的.

我正在使用Visual Studio 2008进行编译.

编辑 – 添加我发送给我的客户的说明

关于Rect问题;如何知道结构在C和C中的大小相同,消除了对“未定义行为”的怀疑.

如果数据结构中字段的实际位置根据编译而变化,则会发生未定义的行为.

您必须将所有成员变量访问视为最终解析为指针,由指向对象存储开头的指针计算,并根据该结构中的内容计算偏移量.

打包和数据对齐设置会影响偏移的值.

允许编译器重新排序类型以获得最佳访问权限 – 这是一种未定义的行为,假设只是因为您按给定顺序声明了两个成员实际存储的顺序.声明命令唯一保证的是初始化,复制和销毁顺序.

但是,当您在同一编译器中讨论给定结构的C和C编译时,使用相同的偏移设置,实际重新排序的可能性实际上为零.

因此,我们唯一需要担心的是字段偏移的任何差异.

对于包含简单的4个短整数的结构,只需确认C版本和C版本的大小相同,即可确保它们的偏移量完全相同.为了更加小心,我们还可以检查结构尺寸= 4 * sizeof(短).

我认为值得添加这些检查但是一旦完成,就没有必要重构代码,因为在C和C中使用单独的类型(或者将正在使用的函数移动到自由函数中)是必需的.

/**
Mac-compatible rectangle type with some operators added for C++ use.
@ingroup QuickdrawPort
*/
struct Rect {
    short                           top;
    short                           left;
    short                           bottom;
    short                           right;

#ifdef __cplusplus
    Rect(short _top=0, short _left=0, short _bottom=0, short _right=0) :
        top(_top),
        left(_left),
        bottom(_bottom),
        right(_right)
    {}
    #ifdef _WINNT_  // WinDef.h has been included
        const Rect& operator=(const tagRECT& rhs) {
            top = short(rhs.top);
            left = short(rhs.left);
            bottom = short(rhs.bottom);
            right = short(rhs.right);
            return *this;
        }

        operator tagRECT() const {
            tagRECT lhs;
            lhs.top = top;
            lhs.left = left;
            lhs.bottom = bottom;
            lhs.right = right;
            return lhs;
        }

    #endif// _WINNT_
    short height() const { return bottom - top; }
    short width() const { return right - left; }
    bool empty() const { return right==left || bottom==top; }

    bool operator==(const Rect& rhs) const {
        return top == rhs.top &&
            left == rhs.left && 
            bottom == rhs.bottom &&
            right == rhs.right;
    }
#endif  
};
#ifndef __cplusplus
typedef struct Rect Rect;
#endif
我是否正确地假设包含此定义的头文件包含在几个翻译单元中,其中一些编译为C,还有一些 – 作为普通C?

如果是,那么您有一个ODR违规,根据C标准,它会调用未定义的行为.

有两种方法可以解决它.

>忽略此未定义行为的实例,前提是您知道它在您需要支持的平台上的确切显示方式. (请注意,未定义的行为可以表现为正确工作的程序).说实话,对于大多数编译器,你不会有问题.但是,您必须了解此代码是通过偶然而非法律运作的.允许编译器对具有成员函数的类使用不同的布局. (我愿意打赌这个代码会在CINT上破坏,例如).>消除未定义的行为.我建议你这样走.有几种可能性.例如,您可以从“C Rect”继承“C Rect”,将后者保持为普通结构.

相关文章
相关标签/搜索