2

I have a const char * (or const string&), and I would like to append a subsection of it to an NSMutableString.

I figured that I could do

// s: const char *
// start, end: size_t
[anNSMutableString appendString:[[NSString alloc] 
    initWithBytesNoCopy:s+start
                 length:end-start  
               encoding:NSUTF8StringEncoding
           freeWhenDone:NO]];

This doesn't work because initWithBytesNoCopy of NSString takes a void * per Apple documentation:

- (instancetype)initWithBytesNoCopy:(void *)bytes 
                             length:(NSUInteger)len 
                           encoding:(NSStringEncoding)encoding 
                       freeWhenDone:(BOOL)freeBuffer;

On the other hand, initWithBytes takes a const void *. Therefore, the above code works if I change it to use initWithBytes.

Question: Why does NSString initWithBytesNoCopy take void * instead of const void *?

Here is my thought process:

  • I assume there is a valid reason that initWithBytesNoCopy is declared to take void * instead of const void *.
  • The only valid reason I can think of is that initWithBytesNoCopy may modifies bytes, or future operations on the newly created NSString may modify its content.
    • However, I don't see how/why initWithBytesNoCopy would modify bytes
    • I also don't see how operation on NSString can modify its contents because NSString is immutable.
  • Dead end. What did I get wrong?
Haozhun
  • 6,331
  • 3
  • 29
  • 50
  • 3
    I suspect because when `freeWhenDone` is YES, it will have to pass the pointer to `free(void*)`. – jtbandes Sep 17 '20 at 03:25
  • @jtbandes, I found https://stackoverflow.com/questions/2819535/unable-to-free-const-pointers-in-c after reading your comment. It looks like it is a contested topic whether operations like free should take `void *` or `const void *`. It's also inconsistent in practice: `free` is defined to take `void *` whereas `delete const_ptr` is allowed. As a result, your suspicion seems plausible. – Haozhun Sep 17 '20 at 05:00

0 Answers0