如何在没有警告的情况下在枚举中定义一个非常大的常量?
How to define a very large constant in an enumeration without a warning?
我正在使用 CMCHTPC MediaFoundation headers,它们似乎可以工作,但它们会在几个我想摆脱的地方给出编译器警告。在大多数情况下,罪魁祸首似乎与以下枚举有关:
TMF_Plugin_Type = (
MF_Plugin_Type_MFT = 0,
MF_Plugin_Type_MediaSource = 1,
MF_Plugin_Type_MFT_MatchOutputType = 2,
MF_Plugin_Type_Other = DWORD(-1)
);
无论最后一个值如何定义,如 DWORD(-1)
或 DWORD($FFFFFFFF)
或简单地如 $FFFFFFFF
,编译器总是回复:
W1012 Constant expression violates subrange bounds
有没有办法在不特别禁止编译器中的警告的情况下修正这个定义? (请注意 {$R-}
不起作用;这会在运行时关闭范围检查,但不会在编译时关闭。)
我想你可以看看 TColor
和 TColorRec
是如何在 System.UITypes
中声明的,并使用 Embarcadero 的经验来声明这样的东西:
TMF_Plugin_Type = [=10=] .. $FFFFFFFF;
TMF_Plugin_Type_Rec = record
const
MF_Plugin_Type_MFT = 0;
MF_Plugin_Type_MediaSource = 1;
MF_Plugin_Type_MFT_MatchOutputType = 2;
MF_Plugin_Type_Other = TMF_Plugin_Type($FFFFFFFF);
end;
您可以将其声明为 -1 并给出一个 {$Z4} 来告诉编译器为此枚举使用 4 个字节:
{$Z4}
type
TMF_Plugin_Type = (
MF_Plugin_Type_MFT = 0,
MF_Plugin_Type_MediaSource = 1,
MF_Plugin_Type_MFT_MatchOutputType = 2,
MF_Plugin_Type_Other = -1);
它也可以在没有编译器指令的情况下工作。文档说:
To assign an ordinality to a value, follow its identifier with = constantExpression, where constantExpression is a constant expression that evaluates to an integer.
值为-1 的整数在内部表示为 4 个字节。所以无论哪种方式都应该有效。
更新:我重新检查了一下,确实需要编译器指令(除非你在项目选项中设置了类似的选项)。
据我所知,你有两个选择。
- 删除
DWORD
转换并将 DWORD(-1)
替换为 -1
,如 Uwe 的回答中所述。
- 抑制这个特定的编译器警告。您可以使用
{$WARN BOUNDS_ERROR OFF}
. 在代码中执行此操作
选项 1 的缺点是您必须找到每个这样的声明并进行更改。这意味着对第三方库进行大规模更改。如果您希望接受该库的新版本,则必须 re-apply 这些更改。对于某些图书馆来说,这可能会有问题。
所以在我看来,抑制警告可能是更简洁的方法。您可以将抑制指令放在包含文件中,或放在单元的开头。这意味着您对第三方代码所做的更改范围更小。
我正在使用 CMCHTPC MediaFoundation headers,它们似乎可以工作,但它们会在几个我想摆脱的地方给出编译器警告。在大多数情况下,罪魁祸首似乎与以下枚举有关:
TMF_Plugin_Type = (
MF_Plugin_Type_MFT = 0,
MF_Plugin_Type_MediaSource = 1,
MF_Plugin_Type_MFT_MatchOutputType = 2,
MF_Plugin_Type_Other = DWORD(-1)
);
无论最后一个值如何定义,如 DWORD(-1)
或 DWORD($FFFFFFFF)
或简单地如 $FFFFFFFF
,编译器总是回复:
W1012 Constant expression violates subrange bounds
有没有办法在不特别禁止编译器中的警告的情况下修正这个定义? (请注意 {$R-}
不起作用;这会在运行时关闭范围检查,但不会在编译时关闭。)
我想你可以看看 TColor
和 TColorRec
是如何在 System.UITypes
中声明的,并使用 Embarcadero 的经验来声明这样的东西:
TMF_Plugin_Type = [=10=] .. $FFFFFFFF;
TMF_Plugin_Type_Rec = record
const
MF_Plugin_Type_MFT = 0;
MF_Plugin_Type_MediaSource = 1;
MF_Plugin_Type_MFT_MatchOutputType = 2;
MF_Plugin_Type_Other = TMF_Plugin_Type($FFFFFFFF);
end;
您可以将其声明为 -1 并给出一个 {$Z4} 来告诉编译器为此枚举使用 4 个字节:
{$Z4}
type
TMF_Plugin_Type = (
MF_Plugin_Type_MFT = 0,
MF_Plugin_Type_MediaSource = 1,
MF_Plugin_Type_MFT_MatchOutputType = 2,
MF_Plugin_Type_Other = -1);
它也可以在没有编译器指令的情况下工作。文档说:
To assign an ordinality to a value, follow its identifier with = constantExpression, where constantExpression is a constant expression that evaluates to an integer.
值为-1 的整数在内部表示为 4 个字节。所以无论哪种方式都应该有效。
更新:我重新检查了一下,确实需要编译器指令(除非你在项目选项中设置了类似的选项)。
据我所知,你有两个选择。
- 删除
DWORD
转换并将DWORD(-1)
替换为-1
,如 Uwe 的回答中所述。 - 抑制这个特定的编译器警告。您可以使用
{$WARN BOUNDS_ERROR OFF}
. 在代码中执行此操作
选项 1 的缺点是您必须找到每个这样的声明并进行更改。这意味着对第三方库进行大规模更改。如果您希望接受该库的新版本,则必须 re-apply 这些更改。对于某些图书馆来说,这可能会有问题。
所以在我看来,抑制警告可能是更简洁的方法。您可以将抑制指令放在包含文件中,或放在单元的开头。这意味着您对第三方代码所做的更改范围更小。