2

我们有两个简单的功能。

#include <stdio.h>

 /* first approach */
int power1(int *ptr)
{
     return *ptr * *ptr;    
}

/* second approach */
int power2(int *ptr)
{
    int tmp = *ptr;
    return tmp*tmp;    
}

int main()
{
    int val = 5;

    printf("%d\n", power1(&val));
    printf("%d\n", power2(&val));

    return 0;
}

哪一个更好?power1 快一点,但我听说 power2 更安全。我不记得为什么?据我记得有一种情况是power1(第一种方法)有瓶颈。你能解释一下吗?安全关键系统是否使用第二种方法?

4

4 回答 4

6

没有一个是好的。你要这个:

#include <stdio.h>

/* second approach */
int power(int operand)
{
    return operand*operand;    
}

int main(void)
{
    int val = 5;    
    printf("%d\n", power(val));
}

现在关于你的两种方法:

power2绝不比power1.

顺便提一句:

正确的声明方式mainint main(void),不需要return 0;结尾的main,如果main不包含声明,则在结尾return有一个隐含的.return 0;main

于 2019-02-21T08:01:25.317 回答
2

哪一个更好?

它们同样好/坏

power1 快一点

如果您在没有任何优化的情况下进行编译,那么“是的,power1 可能会快一点”但是一旦您打开编译器优化,它们(对于任何体面的编译器)将是相等的。

但我听说power2更安全

那是错误的。使用参数列表中的变量与使用局部变量一样安全。

安全关键系统是否使用第二种方法?

没有理由这样做。但是,在某些安全关键系统中禁止使用指针。在您的特定情况下,最好直接传递整数而不是传递指针

与“安全”相关的另一件事是整数溢出。您的代码不能防止整数溢出,并且整数溢出是未定义的行为。因此,对于安全关键系统来说,这可能是需要考虑的事情。

于 2019-02-21T08:17:13.950 回答
1

我希望我知道“安全”在这里应该是什么意思(我看到你的评论说你是从面试中得到的,而且面试官没有解释他的意思)。

函数应该接收指针作为参数的原因只有 4 个:

  1. 该函数旨在更新参数;
  2. 参数为数组表达式,作为函数参数传递时会自动转换为指针表达式;
  3. 该参数是一个非常大struct或类似的聚合类型,创建本地副本被认为过于昂贵;
  4. 该参数是通过malloccalloc或创建的realloc

这些都不应该适用于您发布的片段。对他们来说“最安全”的选择是根本不使用指针。

使用指针的一个“不安全”方面是您可能打算将输入设为只读,但由于您已收到指针,因此您可以修改输入。对于这些情况,您希望const-qualify 该参数:

void foo ( const char *str ) // we cannot modify what str points to
{
  ...
}

使用指针的另一个“不安全”方面是意外(或故意)更新指针值本身以访问您不应该访问的内存:

while ( *ptr )
  do_something_with( ptr++ );

您可以通过将指针声明为const

void bar( int * const ptr ) // we cannot update the value in ptr

但是,这不会阻止您使用[]下标运算符:

while( ptr[i] )
  do_something_with( ptr[i++] );

现在,如果你的面试官正在考虑多个线程或一些与中断或波动有关的机器级问题,那么也许他有一个观点——如果有什么东西可以修改ptr指向当前执行线程控制之外的东西,那么是的,第二种方法在这方面“更安全”(指向的值在计算过程中不会改变)。

但是,如果代码是多线程的并且ptr可以在不同的线程中进行修改,那么对它的访问应该通过互斥锁或其他东西进行同步。如果ptr可以在您的程序控制之外进行更新,则应该声明它volatile

int power1( volatile int *ptr ) { ... }
int power2( volatile int *ptr ) { ... }
于 2019-02-21T18:07:38.350 回答
-1

power1那里将取消引用 2 次 - 将有 2 次与取消引用相关的内存查找。

power2将有取消引用,但只有一次。只在声明中int tmp = *ptr;

因此,power1如果在速度方面以这种方式看待,可能效率低下。

如果您关闭了编译器优化,这是基于假设的。

于 2019-02-21T09:05:43.253 回答