创建并验证进入"if"语句的指针

creating and verifying a pointer into "if" statement

本文关键字:if 语句 指针 验证 创建      更新时间:2023-10-16

这段代码正确吗?

void foo ( int* p )
{
  if ( int* p2 = p ) // single "="
  {
    *p2++;
  }
}

我一直认为它不是,但最近我在一个同事的源代码中看到了这样的代码。

如果"p"是NULL怎么办?MS VS 2008工作正常,但显示"警告C4706:条件表达式中的赋值"。

谢谢。

警告 assignment within conditional expression 通常由编译器发出,以防止您编写

 if (a = b) 
 {
的意思是
 if (a == b) // big difference!
 {

在您的示例中,'赋值警告'实际上是伪造的,因为它实际上不是赋值,而是初始化:

 {
      int *p2 = p;
      if (p2)
      {
      }
 }

并且没有风险您实际上希望语法错误(int *p2 == p ?!)代替:)

你的帖子的其余部分是完全有效的c++ 03(及以后),只是做它所说的1


<一口> 1>

  • p2在没有做任何操作的情况下被解引用
  • p2在没有进行任何操作的情况下递增,

,但我猜这只是样本代码?在不明显的情况下,*p2++相当于*p2; p2++;)

通过提出警告C4706,编译器只是质疑您是否真的想写if ( int* p2 == p )而不是if ( int* p2 = p ),如图所示。

2003年c++标准6.4中,if ( int* p2 = p )是合法的:

初始化的条件 [if (condition)]的值在非switch语句中的声明是值隐式转换为bool类型。

如果pNULL,则条件 (int* p2 = p)失败,因为p2的值为0,因此隐式false,并且*p2 递增。

这在形式上是正确的(在c++中,但在C中不是)dynamic_cast添加了一个条件,以支持以下内容:

if ( Derived* p = dynamic_cast<Derived*>( ptrToBase ) ) {
    //  ...
}

的论点是,永远不会有p出现在
中的时刻作用域,但不为空。在if之后,p不再在作用域中。

这个论证是站不住脚的,因为一方面,如果你加了else,在else块中,p在作用域中,为空。和涉及限制范围的理由确实不是很充分不管怎样,因为如果函数足够长,它就会起作用函数太长太复杂。这个结构支持如:

if ( Derived1* p = dynamic_cast<Derived1*>( ptrToBase ) ) {
    // ...
}
if ( Derived2* p = dynamic_cast<Derived2*>( ptrToBase ) ) {
    // ...
}
// ...

但是在好的代码中,你真的不希望这样做。

总而言之,我会避免这种结构,用以下方式代替:

int* p2 = p;
if ( p2 != NULL ) {
    //  ...
}

它更显式,更可读。这确实意味着p2在范围之外的if,但我认为,如果这导致任何问题,函数本身需要重构,因为它太长太大复杂。

编辑:

关于警告:这是一个完全愚蠢的部分编译器。在条件表达式中没有赋值:没有任务,句号,也没有条件expression”原始代码中的条件是声明,而不是表达式。如果编译器想要警告某些东西(在风格上)理由(因为我同意这是糟糕的风格),然后它应该警告对bool的隐式转换。(当然,是否发出此警告应由选项控制。编译器应该编译语言,而不是强加风格,除非

代码容易出错(为什么不把它分成两个语句),但其他方面是正确的。如果你把它分成:

void foo ( int* p )
{
  int* p2 = p;
  if ( p2 ) 
  {
    *p2++;
  }
}

更容易读,不会给你警告。你可以看到它也是正确的(在null的情况下,你只是将p2赋值为null,这是可以的)。

如果p为NULL,则条件不满足。代码没问题。

这段代码看起来很奇怪。这是正确的,但我看不出它在哪些情况下有用。
它的可读性不如简单的替代方案(如Oren S.提到的),并且不必要地定义一个新变量来增加(*p)。参数p已经是堆栈上的一个新变量了,为什么还要再创建一个呢?

把int* p看作是"p是指向int型的指针"。而且,"p2也是一个指向整型对象的指针"。当你说p2 = p时,你让p2指向p也指向的指针。将地址增加4,并指向您最初指向的int以外的其他对象。它应该是一个32位整数。在32位编译器上,指针以4为单位递增。如果你使用(*p2)++括在括号中,它将使指针所指向的整数自增。

是的,它工作…奇怪。

int ClassPtr::MethodA(int *p){If (int *p2 = p){(* p2) + +;返回* p2;}返回0;}

我认为代码在语法上没有问题。但这不是一个好的风格。如果你确实知道有一个"=",你也可以这样写:

if ((int* p2 = p) != NULL)
{
    *p2++;
}

我更喜欢指针比较NULL。