5

我有以下代码:

int isUsed[6] = {1,1,1,1,1,1};

如果这个数组中的所有元素都等于1,如何比较?还是其他价值?我知道我们可以循环数组并一一比较,但我们还有其他方法吗?

4

7 回答 7

12

是的,您必须逐个元素地进行。

如果您的数组仅包含纯整数类型(即不是 s 数组struct)并且您只想检查是否相等,则可以使用memcmp().

这当然会在内部循环,但它是一个预制的标准函数,因此有助于提高可读性。但它可能会损害性能,因为它比较chars. 另一方面(在评论之后)它可能会因为是一个可以优化的知名库函数而获得性能。

另外,为了完整起见,我对 nostruct上面的警告的原因是结构通常包含填充字节,这将被“看到”memcmp()并可能导致不正确的结果。

例如:

struct {
  int x;
  char y;
  int z;
} a = { 1, 2, 3 }, b = { 1, 2, 3 };

在许多系统上,上述struct内容将在 和 之间进行填充yz这可能会导致不正确的结果,memcmp()因为填充字节具有未定义的值。

于 2013-07-05T12:21:52.023 回答
4

对于原始数据类型(不是结构),如果您知道数组的大小以及您要比较的内容:memcmp将完成这项工作:

#include <stdio.h>
#include <string.h>

static int allOnes[6] = {1,1,1,1,1,1};

int main(int argc, const char* argv[]) {

   int isUsed[6] = {1,1,1,1,1,1};

   if( memcmp( isUsed, allOnes, sizeof allOnes ) == 0 )
       printf( "Array has only 1's\n" );
   else
       printf( "At least one element is not 1\n" );
}

编辑:关于性能...

一些评论提到了memcmp和循环的性能,包括展开的循环。

下面是一个简单的测试程序来衡量性能。在我的机器(Mac OS X,LLVM 编译器)中,这是我得到的:

memcmp: 0.036031 seconds result=1
loop: 0.097180 seconds result=1
unrolled loop: 0.075623 seconds result=1

在对上述数字做出具体评论之前,请注意:

  • 我并没有提出一般性的主张,只是表明在我的环境中,该memcmp解决方案大大优于其他解决方案。
  • 我拥有的循环展开并不是最好的实现。这只是一个粗略的尝试,让一些循环展开到位。

随意修改代码并发布其他数字。

#include <stdio.h>
#include <string.h>
#include <time.h>

static int allOnes[6] = {1,1,1,1,1,1};

bool compareWithMemcmp()
{
       int isUsed[6] = {1,1,1,1,1,1};
       return memcmp( isUsed, allOnes, sizeof allOnes ) == 0;
}

bool compareWithLoop()
{
       int isUsed[6] = {1,1,1,1,1,1};
       for( int i = 0; i < sizeof allOnes / sizeof allOnes[0]; i++)
           if( isUsed[i] != 1 )
               return false;
       return true;
}

bool compareWithUnrolledLoop()
{
       int isUsed[6] = {1,1,1,1,1,1};
       // IMPORTANT: doesn't account for odd-length array
       for( int i = 0; i < sizeof allOnes / sizeof allOnes[0]; i += 2)
           if( (isUsed[i] != 1) || (isUsed[i+1] != 1) )
               return false;
       return true;
}

int main(int argc, const char* argv[]) {

    bool result;

    clock_t begin = clock();
    for( int i = 0; i < 10000000; i++ )
       result = compareWithMemcmp();
    printf( "memcmp: %f seconds result=%d\n",
            (double)(clock() - begin) / CLOCKS_PER_SEC, result );

    begin = clock();
    for( int i = 0; i < 10000000; i++ )
       result = compareWithLoop();
    printf( "loop: %f seconds result=%d\n",
            (double)(clock() - begin) / CLOCKS_PER_SEC, result );

    begin = clock();
    for( int i = 0; i < 10000000; i++ )
       result = compareWithUnrolledLoop();
    printf( "unrolled loop: %f seconds result=%d\n",
            (double)(clock() - begin) / CLOCKS_PER_SEC, result );
}
于 2013-07-05T12:32:55.433 回答
2

您必须一一比较数组元素。

于 2013-07-05T12:21:56.347 回答
0

好吧,我不同意任何说没有其他办法的答案...

答案取决于如何更改数组。

给定一个预先设置为某个已知值的数组,并且没有进一步的更改,测试很简单,解决方案是 O(1)。这一切都是1因为你做到了。

一旦您开始更改值,如果它们的更改方式存在某种模式,那么您可能能够记录有关该模式本身的信息,并且可以在小于 O(n) 的时间内针对历史进行测试。

例如,当您更改数组中的一个元素时,您可能会在别处设置一个标志,指示数组的哪些部分需要重新计算。如果所有更改都聚集在一个小区域中,那么您可能只需要测试阵列的一小部分。

但是,在给出的特定示例中,一个小的数组isUsed[],假设每个元素只有两种可能的状态可能是合理的。如果您为此使用了位掩码,那么测试整个数组可能是一个整数运算。它确实会隐式访问每个元素,但它比循环更有效。

于 2013-07-05T16:11:15.077 回答
0

您可以使用内联汇编,取自以下示例:

您可以编写一个宏来重复此代码 6 次,关于您的问题:

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>


int64_t isUsed[ 1 ] = { 1 };

int main ( void )
{

 __asm__
(
    "\n movq  %[a] , %%rax"
    "\n cmpq  $1 , %%rax"
    :
    : [ a ] "m" ( isUsed[0] )
);

__asm__ goto ("jne %l0\n"
: 
: 
: 
: NotEqual);


printf ("\n Array Contains 1 in all elements");
return 1 ;

NotEqual:

printf ("\n Array Not contains 1 in all elements");

return 0 ;
}

这是汇编代码:(小)

 movq  isUsed(%rip) , %rax
 cmpq  $1 , %rax
 jne .L2

注意您将使用的整数类型( int32_t 或 int64_t : inttypes.h )

于 2013-07-05T14:59:57.727 回答
0

你可以你 gcc 扩展:

#include <stdio.h>
#include <inttypes.h>

#define VECTOR_SIZE         4
typedef int v4int __attribute__ ((vector_size(sizeof(int32_t)*VECTOR_SIZE))); 


typedef union f4vector   
{
 v4int       v;
 __int128_t   value ;
} f4vector;



int main()
{
union f4vector a, b, c;

a.v = (v4int) { 1, 1, 1, 2 }; // your vector
b.v = (v4int) { 1, 1, 1, 1 };

c.v = a.v - b.v;

if ( c.value == 0 )
    puts ( "array contains all 1");
else
    puts ("array Not contais all 1");

return 0 ;
}
于 2013-07-05T15:26:50.837 回答
0

除了一次比较每个元素之外,别无他法。虽然它会减慢你的速度,但别无选择。尝试

#define NULL (void*)0
memcmp(char* source, const char * dest, int count);

如果 String 匹配,则返回 NULL。

于 2013-07-05T12:27:53.910 回答