我有以下代码:
int isUsed[6] = {1,1,1,1,1,1};
如何比较此数组中的所有元素是否等于1?还是其他价值? 我知道我们可以循环数组并逐一比较它,但我们还有其他方法可以做到吗?
答案 0 :(得分:12)
是的,你必须逐个元素地做。
如果你的数组只包含纯整数类型(即不是struct
的数组),你只想检查是否相等,你可以使用memcmp()
。
这当然是在内部循环,但它是一个预制的标准功能,因此它有助于提高可读性。但可能会损害性能,因为它会比较char
s。另一方面(在评论之后),由于可能是一个众所周知的库函数,它可能会获得性能。
另外,为了完整性,我之前有关于struct
以上的警告的原因是结构通常包含填充字节,这将是"看到"按memcmp()
,可能会导致错误的结果。
例如:
struct {
int x;
char y;
int z;
} a = { 1, 2, 3 }, b = { 1, 2, 3 };
在许多系统上,上述struct
将在y
和z
之间填充,这可能会导致memcmp()
的结果不正确,因为填充字节具有未定义的值。
答案 1 :(得分: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 );
}
答案 2 :(得分:2)
您必须逐个比较数组元素。
答案 3 :(得分:0)
除了一次比较每个元素之外别无他法。虽然它减慢了你的速度,但别无选择。试试
#define NULL (void*)0
memcmp(char* source, const char * dest, int count);
如果String匹配,返回NULL。
答案 4 :(得分: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)
答案 5 :(得分: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 ;
}
答案 6 :(得分:0)
嗯,我不同意任何回答说没有别的办法......
答案取决于数组的更改方式。
给定一个你预先设置为某个已知值的数组,并且没有进一步的更改,测试很简单,解决方案是O(1)。这都是1
,因为你做到了。
一旦你开始改变这些值,如果它们的改变方式存在某种模式,那么你可能能够记录该模式本身的信息,并且可以在小于O(n)的情况下对历史进行测试。 )。
例如,当您更改数组中的一个元素时,您可以在其他位置设置一个标志,指示数组的哪些部分需要重新评估。如果所有更改都聚集在一个小区域中,那么您可能只需要测试数组的一小部分。
但是,在给定的特定示例中,小数组isUsed[]
,假设每个元素只有两个可能的状态可能是合理的。如果您使用了bit-mask,那么测试整个数组可能是一个整数操作。它确实隐式访问每个元素,但它比循环更有效。