Objective-C では、C 配列をプロパティ型として使用できないことはわかっています。その場合、予想されるコンパイラエラーが発生します。
しかし、構造体プロパティ内の C 配列に関して私が見ている動作には驚いています。
- コンパイル エラーや警告はありません。
- アドレス自体の予期しないアドレス (gdb
info malloc
はそれについて知りません。それが初期化されていないメモリなのかどうかはわかりません。しかし、メモリが破損しているにもかかわらず、クラッシュするか、明らかに動作していると予想されます)。 - 割り当てはノーオペレーションになります。
このサンプルコードを煮詰めました:
#import <Foundation/Foundation.h>
#ifndef sizeofA
#define sizeofA(array) (sizeof(array)/sizeof(array[0]))
#endif
@interface IncludeCArrayDirectly : NSObject // Doesn't even compile
// Uncomment below to see the compilation error for yourself.
//@property(nonatomic, assign) int8_t f[9]; // ERROR: Property cannot have array or function type 'int8_t [9]'
@end
@interface IncludeCArrayInStruct : NSObject // Compiles (no warning) and runs but is amazingly broken.
@property(nonatomic, assign) int normalProperty;
@property(nonatomic, assign) struct { int f[9]; } p;
- (void*)normalPropertysAddress;
@end
@interface IncludeCArrayInIvar : NSObject { // Totally works.
@public
int normalIvar;
int8_t f[9];
}
@end
int main(int argc, const char *argv[]) {
@autoreleasepool {
{{
IncludeCArrayInStruct *a = [IncludeCArrayInStruct new];
// Notice a.p.f's address is off in 0x7fffxxxx-land:
printf("&a = %p, &a.normalProperty = %p, a.p.f = %p\n",
a, [a normalPropertysAddress], a.p.f);
printf("a.p.f[4] BEFORE %d\n", a.p.f[4]);
a.p.f[4] = 42;
printf("a.p.f[4] AFTER %d\n", a.p.f[4]);
assert(a.p.f[4] == 0); // Surprise! Assertion passes. Assignment above is a no-op.
// Dump all of a.p.f just to take a better look:
for (unsigned i = 0; i < sizeofA(a.p.f); i++) {
printf("a.p.f[%d] == %d\n", i, a.p.f[i]);
}
}}
{{
IncludeCArrayInIvar *b = [IncludeCArrayInIvar new];
// All these addresses are about what you'd expect:
printf("&b = %p, &b.normalIvar = %p, b.f = %p\n",
b, &b->normalIvar, b->f);
printf("b->f[4] BEFORE %d\n", b->f[4]);
b->f[4] = 42;
printf("a->f[4] AFTER %d\n", b->f[4]);
assert(b->f[4] == 42); // No surprise here, above assignment worked.
// Dump all of b.f just to take a better look:
for (unsigned i = 0; i < sizeofA(b->f); i++) {
printf("b->f[%d] == %d\n", i, b->f[i]);
}
}}
}
return 0;
}
@implementation IncludeCArrayDirectly
@end
@implementation IncludeCArrayInStruct
- (void*)normalPropertysAddress {
return &_normalProperty;
}
@end
@implementation IncludeCArrayInIvar
@end
上記の私のパズルポイントの説明はありますか?