草庐IT

c++ - C 和 C++ 的结构定义不同——它安全吗? PC-Lint 警告

coder 2024-02-17 原文

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

PC-Lint 报告错误 114:标记“Rect”的结构声明不一致,但我确信它是安全的。

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

编辑 - 添加我发送给客户的解释

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

如果字段在数据结构中的实际位置因编译而异,则会出现未定义的行为。

您必须将所有成员变量访问视为最终解析为指针,该指针由指向对象存储开头的指针加上偏移量(取决于该结构中的内容)计算得出。

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

允许编译器对类型重新排序以实现最佳访问 - 假设仅仅因为您以给定顺序声明了两个成员而实际上它们是按该顺序存储的,这是未定义的行为。声明顺序唯一保证的是初始化、复制和销毁顺序。

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

因此,我们唯一需要担心的是字段偏移量的差异。

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

我认为添加这些检查是值得的,但一旦完成,就不需要重构代码,因为在 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++ 标准,调用未定义的行为。

有两种处理方法。

  1. 忽略此未定义行为实例,前提是您知道它在您需要支持的平台上的确切表现。 (请注意,未定义的行为可以表现为一个正常工作的程序)。说实话,对于大多数编译器,你在这里不会有问题。但是,您必须了解此代码是偶然发生的,而不是法律规定的。允许编译器对有成员函数的类使用与没有成员函数的类不同的布局。 (我敢打赌这段代码会在 CINT 上中断,例如)。

  2. 消除未定义的行为。我建议你走这条路。有几种可能性可以做到这一点。例如,您可以从“C Rect”继承“C++ Rect”,将后者保留为普通的 struct

关于c++ - C 和 C++ 的结构定义不同——它安全吗? PC-Lint 警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5140893/

有关c++ - C 和 C++ 的结构定义不同——它安全吗? PC-Lint 警告的更多相关文章

  1. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  2. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  3. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  4. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  5. ruby - 在院子里用@param 标签警告 - 2

    我试图使用yard记录一些Ruby代码,尽管我所做的正是所描述的here或here#@param[Integer]thenumberoftrials(>=0)#@param[Float]successprobabilityineachtrialdefinitialize(n,p)#initialize...end虽然我仍然得到这个奇怪的错误@paramtaghasunknownparametername:the@paramtaghasunknownparametername:success然后生成的html看起来很奇怪。我称yard为:$yarddoc-mmarkdown我做错了什么?

  6. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  7. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  8. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  9. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  10. ruby-on-rails - active_admin 目录中的常量警告重新声明 - 2

    我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA

随机推荐