Standart C'de eşitlik için iki yapı örneğini nasıl karşılaştırıyorsunuz?
Standart C'de eşitlik için iki yapı örneğini nasıl karşılaştırıyorsunuz?
Yanıtlar:
C bunu yapmak için herhangi bir dil olanağı sunmaz - bunu kendiniz yapmanız ve her yapı üyesini üye ile karşılaştırmanız gerekir.
0.0, -0.0 NaN
bir problemdir memcmp()
. İkili gösterimde farklılık gösteren işaretçiler aynı konuma işaret edebilir (örn. DOS: seg: offset) ve bu nedenle eşittir. Bazı sistemlerde eşit olarak karşılaştırılan birden fazla boş gösterici bulunur. int
Gereksiz kodlamalara sahip -0 ve kayan nokta türleri için belirsiz . (Intel long double, ondalık64 vb.) Bu sorunlar calloc()
kullanılmaz veya kullanılmaz veya dolgu olmaz.
==
benim gibi yapılarla çalışmadığını merak ediyorsanız , lütfen bkz. Stackoverflow.com/questions/46995631/…
Kullanmak isteyebilirsiniz memcmp(&a, &b, sizeof(struct foo))
, ancak her durumda çalışmayabilir. Derleyici bir yapıya hizalama arabellek alanı ekleyebilir ve ara bellek alanında bulunan bellek konumlarında bulunan değerlerin belirli bir değer olacağı garanti edilmez.
Kullanmak Ama eğer calloc
yoksa memset
bunları kullanmadan önce yapıların tam boy, sen yapabilirsiniz bir yapmak sığ olan karşılaştırma memcmp
(Yapınızın işaretçileri içeriyorsa işaretçileri işaret ediyor adresi aynı ise, sadece maç olacak).
memcmp
hafızanın ilk önce temizlenmesi şartıyla sığ bir karşılaştırma yapabileceğinizi söylüyor . Hangi çalışmaya yakın ama doğru değil. Ofc sorusu aynı zamanda "eşitlik" i tanımlamaz, bu yüzden eğer bunu "nesne gösteriminin bayt-bilge eşitliği" memcmp
olarak adlandırırsanız, tam olarak bunu yapar (hafızanın silinip temizlenmediği).
Çok yaparsanız, iki yapıyı karşılaştıran bir fonksiyon yazmanızı öneririm. Bu şekilde, yapıyı değiştirirseniz, karşılaştırmayı tek bir yerde değiştirmeniz yeterlidir.
Nasıl yapılacağı konusunda .... Her elemanı ayrı ayrı karşılaştırmanız gerekir
Memcmp'yi, yapılardaki alan arasındaki olası rastgele doldurma karakterleri nedeniyle eşitlik yapılarını karşılaştırmak için kullanamazsınız.
// bad
memcmp(&struct1, &struct2, sizeof(struct1));
Yukarıdaki gibi bir yapı için başarısız olacaktır:
typedef struct Foo {
char a;
/* padding */
double d;
/* padding */
char e;
/* padding */
int f;
} Foo ;
Güvende olmak için üye bazında karşılaştırmayı kullanmalısınız.
@Greg, genel durumda açık karşılaştırma işlevleri yazmak zorunda olduğu doğrudur.
Aşağıdaki durumlarda kullanmak mümkündür memcmp
:
NaN
.-Wpadded
bunu kontrol etmek için clang ile kullanın ) VEYA yapılar başlangıçta açıkça memset
başlatılır.BOOL
farklı ancak eşdeğer değerlere sahip üye türleri (Windows gibi ) yoktur .Gömülü sistemler için programlama yapmıyorsanız (veya bunlarda kullanılabilecek bir kitaplık yazmıyorsanız), C standardındaki bazı köşe durumları için endişe etmem. Yakın veya uzak işaretçi ayrımı 32 veya 64 bit aygıtlarda mevcut değildir. Bildiğim gömülü olmayan sistemde birden fazla NULL
işaretçi yok.
Başka bir seçenek de eşitlik işlevlerini otomatik olarak oluşturmaktır. Yapı tanımlarınızı basit bir şekilde düzenlerseniz, basit yapı tanımlarını işlemek için basit metin işlemeyi kullanmak mümkündür. Genel durum için libclang kullanabilirsiniz - Clang ile aynı ön ucu kullandığından, tüm köşe vakalarını doğru şekilde işler (engelleme hataları).
Böyle bir kod üretme kütüphanesi görmedim. Ancak, nispeten basit görünüyor.
Bununla birlikte, bu tür oluşturulan eşitlik işlevlerinin uygulama düzeyinde genellikle yanlış bir şey yapması da söz konusudur. Örneğin, UNICODE_STRING
Windows'daki iki yapı sığ mı yoksa derinden mi karşılaştırılmalıdır?
Tüm üyeleri (bir kerede) başlatmadığınız sürece, doldurma konusunda endişelenmeden statik olmayan yapılarda memcmp () kullanabileceğinizi unutmayın. Bu C90 ile tanımlanır:
{0, }
Ayrıca herhangi bir dolgu baytını sıfırlayacak şekilde belirtilmiş mi?
Bu, sorduğunuz sorunun olup olmadığına bağlıdır:
Aynı nesne olup olmadıklarını öğrenmek için, işaretçileri eşitlik için iki yapı ile karşılaştırın. Genel olarak aynı değere sahip olup olmadıklarını öğrenmek istiyorsanız, derin bir karşılaştırma yapmanız gerekir. Bu, tüm üyelerin karşılaştırılmasını içerir. Üyeler başka yapılara işaret ederse, bu yapılara da başvurmanız gerekir.
Yapıların işaretçi içermediği özel durumda, verilerin ne anlama geldiğini bilmek zorunda kalmadan her birinde bulunan verilerin bitsel olarak karşılaştırılmasını yapmak için bir memcmp yapabilirsiniz.
Her üye için 'eşittir' ne anlama geldiğini bildiğinizden emin olun - ints için açıktır, ancak kayan nokta değerleri veya kullanıcı tanımlı türler söz konusu olduğunda daha incedir.
memcmp
yapıyı memcmp
karşılaştırmaz, ikiliyi karşılaştırır ve yapıda her zaman çöp vardır, bu nedenle her zaman karşılaştırmada Yanlış çıkar.
Öğeyi öğeye göre güvenli olarak karşılaştırın ve başarısız olmaz.
Yapılar sadece ilkel içeriyorsa veya katı eşitlikle ilgileniyorsanız, böyle bir şey yapabilirsiniz:
int my_struct_cmp (const struct my_struct * lhs, const yapısal my_struct * rhs) { dönüş memcmp (lhs, rsh, sizeof (struct my_struct)); }
Bununla birlikte, yapılarınız diğer yapılara veya sendikalara işaretçiler içeriyorsa, ilkelleri doğru bir şekilde karşılaştıran bir işlev yazmanız ve diğer yapılarla uygun şekilde karşılaştırma çağrıları yapmanız gerekecektir.
Ancak, ADT başlatmanızın bir parçası olarak yapıların bellek aralığını sıfırlamak için memset (& a, sizeof (struct my_struct), 1) kullanmanız gerektiğini unutmayın.
Bu uyumlu örnek, yapı üyelerinin olabildiğince sıkı paketlenmesini sağlamak için Microsoft Visual Studio'dan #pragma pack derleyici uzantısını kullanır:
#include <string.h>
#pragma pack(push, 1)
struct s {
char c;
int i;
char buffer[13];
};
#pragma pack(pop)
void compare(const struct s *left, const struct s *right) {
if (0 == memcmp(left, right, sizeof(struct s))) {
/* ... */
}
}