我有以下代碼:我們是否需要比較C中數組的每個元素?
int isUsed[6] = {1,1,1,1,1,1};
如何比較,如果這一切的數組中的元素都等於1?或其他價值? 我知道我們可以循環數組並逐個比較它,但是我們有其他方法可以做到嗎?
我有以下代碼:我們是否需要比較C中數組的每個元素?
int isUsed[6] = {1,1,1,1,1,1};
如何比較,如果這一切的數組中的元素都等於1?或其他價值? 我知道我們可以循環數組並逐個比較它,但是我們有其他方法可以做到嗎?
是的,你必須做到元素。
如果您的數組僅包含純整數類型(即不是數組struct
s),並且您只是想檢查相等性,則可以使用memcmp()
。
這當然會在內部循環,但它是預製的標準功能,因此它有助於可讀性。它可能雖然傷害表現,因爲它比較char
s。另一方面(評論之後),它可能會因爲可能被優化的衆所周知的庫函數而獲得性能。
另外,爲了完整性,我對上述沒有struct
s的警告的原因是結構通常包含填充字節,它將被memcmp()
「看到」,並且可能導致錯誤的結果。
例如:
struct {
int x;
char y;
int z;
} a = { 1, 2, 3 }, b = { 1, 2, 3 };
在許多系統中,上述struct
將具有y
和z
之間填充,這可能會從memcmp()
由於填充字節具有未定義的值會導致一個不正確的結果。
是的,它是純整數 – user2131316
*它可能會損害性能*?即使在循環展開或甚至特殊的機器指令支持之後? – johnchen902
@ johnchen902爲什麼會傷害表現? 'memcmp()'是很好的建議。 –
您必須逐個比較數組元素。
對於原始數據類型(非結構),如果你知道數組的大小和你想比較反對什麼: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);
}
可以使用裝配直列,採取從這個例子:
你可以寫一個宏來重複這個代碼的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)
你可以,但是如果你提高了優化級別,你的代碼會比編譯器產生的代碼慢得多。玩組裝很有趣,可以擊敗編譯器 - 但除非你的名字是Agner Fog(或者同樣特殊的人),否則你不會這樣做。 –
@NikBougalis,但是如果你沒有試圖擊敗編譯器,你會如何獲得像Agner Fog這樣的酷名字......? –
@gradyplayer這是一個公平點 - 嘗試沒有錯。我確實說過和組裝一起玩很有趣;) –
你可以在你的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 ;
}
好吧,我不隨着那說,有沒有其他辦法的任何答案去...
答案取決於陣列可以如何改變。
給定一個數組,你已經預先設定了一些已知的值,沒有進一步的變化,測試是微不足道的,解決方案是O(1)。全部是1
,因爲你是這麼做的。
一旦你開始改變這些值,如果它們的改變方式存在某種模式,那麼你可能能夠在該模式本身上記錄信息,並且可以在小於O的情況下對歷史進行測試( N)。
例如,當您更改數組中的一個元素時,您可能會在別處設置一個標誌,指示數組的哪些部分需要重新評估。如果所有的改動都聚集在一個小區域,那麼你可能只需要測試一小部分數組。
但是,在給出的具體例子中,一小組isUsed[]
,假設每個元素只有兩種可能的狀態可能是合理的。如果你使用了一個位掩碼,那麼測試整個數組可能是一個整數操作。它隱式訪問每個元素,但它比循環更有效率。
答案是否定的。不可能訪問每個元素。 –
爲什麼你對你所知道的方式不滿意,即循環數組和逐個比較元素?你覺得這是不是最理想的?如果是這樣,爲什麼? –
是的,我覺得如果我們有一個c庫方法 – user2131316