0

I have a static array of NSString defined in my implementation file like so:

NSString * const knames[] = { @"", @"", @"", ..., @"" };

and what I'd like to do is get the length dynamically. Since this is a C array, length and count are not valid, so I've tried using sizeof:

int count = (sizeof knames) / (sizeof knames[0]);

However, it results in the error message:

Invalid application of 'sizeof' to an incomplete type 'NSString *const _strong[]'

Cœur
  • 37,241
  • 25
  • 195
  • 267
smaili
  • 1,245
  • 9
  • 18
  • I'm not familiar with objective C only C. But would this work sizeof(*knames) since knames is a pointer to an array? – Tobias Johansson May 30 '16 at 20:49
  • @TobiasJohansson great suggestion! That actually makes the error message go away, however yields incorrect results :) – smaili May 30 '16 at 21:12

1 Answers1

0

Small typo; sizeof requires brackets:

/*const?*/ int count = sizeof(knames) / sizeof(knames[0]);

You could create a macro somewhere globally:

#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
...

const int count = ARRAY_SIZE(knames);
trojanfoe
  • 120,358
  • 21
  • 212
  • 242
  • @smaili I don't see why you are still getting an error. Please check you have typed it correctly. However the "incomplete type" bit of the error message is a clue. Are you sure it's in scope? – trojanfoe May 30 '16 at 20:49
  • This answers the question that was posted, but beware. ARC will not memory-manage objects that are saved into a C array. The code @smaili posted will work because all of the strings are statically defined. If you try to put a dynamically created string into a C array the reference in the array will be __unsafe_unretained, meaning that it will not keep ownership of the object, nor will it get set to nil if the object gets deallocated. You'd be much better off using an NSArray of string objects. – Duncan C May 30 '16 at 20:59
  • @DuncanC True. I think the compiler will throw some sort of *... is not a compile-time constant* error in that case anyway. – trojanfoe May 30 '16 at 21:01
  • Yes, if you try to create a compile-time array that includes dynamically created objects, it would throw an error. There would be nothing stopping you from replacing an entry in the C array with a different object once it was created however, and that would be bad. Same issue if you `malloc()` a C array of pointers and try to save objects into it, but for malloc'ed C arrays sizeof doesn't work. You have to remember the size of the array and pass it around, as @dashblinkenlight says in his answer. The long and the short of it is that C arrays are not a good place to store `NSObject`s. – Duncan C May 30 '16 at 21:05
  • @trojanfoe I'm not sure why, but it's definitely in scope. – smaili May 30 '16 at 21:07
  • So this is a "how do I...?" "Don't do that." situation. – Duncan C May 30 '16 at 21:07
  • Interesting, so apparently your solution *does work* if I have that line set in the same implementation file. *However*, when trying to get the size in a different implementation file, that error message appears...so what I'll do is just have an additional integer constant for all files to refer to. – smaili May 30 '16 at 21:11