Does const go before or after CGFloat? - objective-c

Does it even matter? Const before or const after? I'm guessing that whether I put const before or after CGFloat it makes the value of CGFloat constant, but what about the pointer? Is this right for Objective-C:
// Example.h
extern CGFloat const kPasscodeInputBoxWidth;
// Example.m
CGFloat const kPasscodeInputBoxWidth = 61.0f;

It can go either before or after. In the case of a pointer, what matters is whether the const ends up before or after the asterisk:
const int *a; // pointer to const int -- can't change what a points at
int const *a; // same
int *const a; // const pointer to int -- can't change the pointer itself.
// Note: must be initialized, since it can't be assigned.

It doesn't matter (I've always used the former, but I guess it's a matter of style):
const CGFloat kPasscodeInputBoxWidth = 61.0;
CGFloat const kPasscodeInputBoxWidth = 61.0;
At least in the current rendition of CGFloat, it's just a typedef of double, so do as you would with a regular primitive datatype. For pointers, the placement of const will determine if it's the pointer or the value that is constant, so for that it does matter.

Related

Incompatible block pointer type initializing float

Im not sure how to get this to work: I was thinking something to do with typedef, but I can't find much on the subject.
float (^pixelsToDistance)(float, float, NSString *) = ^(float distance, float scale, NSString *conversion)
{
// Code goes here
}
Im trying to return a float value from this block function.
Should I use a function instead?
You were close. You want:
float (^pixelsToDistance)(float, float, NSString *) = ^float(float distance, float scale, NSString *conversion) { ... };
Note the return type after the ^ on the right hand side of the assignment operator.
As the commentator points out, you can omit the return type if it's clear to the compiler what you're returning from the block. E.g.:
float (^pixelsToDistance)(float, float, NSString *) = ^(float distance, float scale, NSString *conversion) { return 0.0f };

Programmatically get all frame variables in objective-c

I'm trying to create my own custom assert. However, I would like my assertion to automatically include all of the relevant variables. This seems really basic to me, and I've searched around for about an hour but I can't seem to find a way get access to all the relevant stack frame variables. Does anyone know how to get these variables?
FYI - I don't need to access the variables in the debugger, I need to access them programmatically. I would like to upload them along with the crash report to give me more information about the crash. I also know that I can print them out manually...that is exactly what I'm looking to avoid.
You are basically asking to re-invent a good sized chunk of the debugger.
Without symbols, there isn't anything you can interrogate to figure out the layout of the local frame. Even with symbols, it is quite likely that the optimizer will have stomped on any local variables as the optimizer will re-use stack slots at whim once it determines the variable is no longer needed within the frame.
Note that many crashes won't be able to be caught at all or, if caught, the frame within which they occurred will have long since been destroyed.
Since you mention that you are creating a custom assertion, it sounds like you really aren't looking to introspect crashes as much as dump a snap of the local frame when you programatically detect that things have gone off the rails. While there really isn't a means of automatically reporting on local stack state, you could do something like:
{ ... some function ....
... local variables ...
#define reportblock ^{ ... code that summarizes locals ... ; return summary; }
YourAssert( cond, "cond gone bad. summary: %#", reportblock());
}
Note that the #define ensures that each YourAssert() captures the state at the time of the assertion. Note also that the above might have a potentially significant impact on performance.
Note also that I just made that code up. It seems like it is worthy of investigation, but may prove non-viable for a number of reasons.
If you're willing to use Objective-C++, then this is definitely a possibility, as long as you are also willing to declare your variables differently, and understand that you will only be able to grab your own variables with this method.
Also note that it will increase your stack frame size with extra __stack_ variables, which could cause memory issues (although I doubt it, personally).
It won't work with certain constructs such as for-loops, but for 95% of cases, this should work for what you need:
#include <vector>
struct stack_variable;
static std::vector<const stack_variable *> stack_variables;
struct stack_variable {
void **_value;
const char *_name;
const char *_type;
const char *_file;
const char *_line;
private:
template<typename T>
stack_variable(const T& value, const char *type, const char *name, const char *file, const char *line) : _value((void **) &value), _type(type), _name(name), _file(file), _line(line) {
add(*this);
}
static inline void add(const stack_variable &var) {
stack_variables.push_back(static_cast<const stack_variable *>(&var));
}
static inline void remove(const stack_variable &var) {
for (auto it = stack_variables.begin(); it != stack_variables.end(); it++) {
if ((*it) == &var) {
stack_variables.erase(it);
return;
}
}
}
public:
template<typename T>
static inline stack_variable create(const T& value, const char *type, const char *name, const char *file, const char *line) {
return stack_variable(value, type, name, file, line);
}
~stack_variable() {
remove(*this);
}
void print() const {
// treat the value as a pointer
printf("%s:%s - %s %s = %p\n", _file, _line, _type, _name, *_value);
}
static void dump_vars() {
for (auto var : stack_variables) {
var->print();
}
}
};
#define __LINE_STR(LINE) #LINE
#define _LINE_STR(LINE) __LINE_STR(LINE)
#define LINE_STR _LINE_STR(__LINE__)
#define LOCAL_VAR(type, name, value)\
type name = value;\
stack_variable __stack_ ## name = stack_variable::create<type>(name, #type, #name, __FILE__, LINE_STR);\
(void) __stack_ ## name;
Example:
int temp() {
LOCAL_VAR(int, i_wont_show, 0);
return i_wont_show;
}
int main(){
LOCAL_VAR(long, l, 15);
LOCAL_VAR(int, x, 192);
LOCAL_VAR(short, y, 256);
temp();
l += 10;
stack_variable::dump_vars();
}
Output (note the junk extra bytes for the values smaller than sizeof(void *), there isn't much I can do about that):
/Users/rross/Documents/TestProj/TestProj/main.mm:672 - long l = 0x19
/Users/rross/Documents/TestProj/TestProj/main.mm:673 - int x = 0x5fbff8b8000000c0
/Users/rross/Documents/TestProj/TestProj/main.mm:674 - short y = 0xd000000010100
Threads will royally screw this up, however, so in a multithreaded environment this is (almost) worthless.
I decided to add this as a separate answer, as it uses the same approach as my other one, but this time with an all ObjC code. Unfortunately, you still have to re-declare all of your stack variables, just like before, but hopefully now it will work better with your existing code-base.
StackVariable.h:
#import <Foundation/Foundation.h>
#define LOCAL_VAR(p_type, p_name, p_value)\
p_type p_name = p_value;\
StackVariable *__stack_ ## p_name = [[StackVariable alloc] initWithPointer:&p_name\
size:sizeof(p_type)\
name:#p_name\
type:#p_type\
file:__FILE__\
line:__LINE__];\
(void) __stack_ ## p_name;
#interface StackVariable : NSObject
-(id) initWithPointer:(void *) ptr
size:(size_t) size
name:(const char *) name
type:(const char *) type
file:(const char *) file
line:(const int) line;
+(NSString *) dump;
#end
StackVariable.m:
#import "StackVariable.h"
static NSMutableArray *stackVariables;
#implementation StackVariable {
void *_ptr;
size_t _size;
const char *_name;
const char *_type;
const char *_file;
int _line;
}
-(id) initWithPointer:(void *)ptr size:(size_t)size name:(const char *)name type:(const char *)type file:(const char *)file line:(int)line
{
if (self = [super init]) {
if (stackVariables == nil) {
stackVariables = [NSMutableArray new];
}
_ptr = ptr;
_size = size;
_name = name;
_type = type;
_file = file;
_line = line;
[stackVariables addObject:[NSValue valueWithNonretainedObject:self]];
}
return self;
}
-(NSString *) description {
NSMutableString *result = [NSMutableString stringWithFormat:#"%s:%d - %s %s = { ", _file, _line, _type, _name];
const uint8_t *bytes = (const uint8 *) _ptr;
for (size_t i = 0; i < _size; i++) {
[result appendFormat:#"%02x ", bytes[i]];
}
[result appendString:#"}"];
return result;
}
+(NSString *) dump {
NSMutableString *result = [NSMutableString new];
for (NSValue *value in stackVariables) {
__weak StackVariable *var = [value nonretainedObjectValue];
[result appendString:[var description]];
[result appendString:#"\n"];
}
return result;
}
-(void) dealloc {
[stackVariables removeObject:[NSValue valueWithNonretainedObject:self]];
}
#end
Example:
#include "StackVariable.h"
int temp() {
LOCAL_VAR(int, i_wont_show, 0);
return i_wont_show;
}
int main(){
LOCAL_VAR(long, l, 15);
LOCAL_VAR(int, x, 192);
LOCAL_VAR(short, y, 256);
temp();
l += 10;
puts([[StackVariable dump] UTF8String]);
}
Output:
/Users/rross/Documents/TestProj/TestProj/main.m:676 - long l = { 19 00 00 00 00 00 00 00 }
/Users/rross/Documents/TestProj/TestProj/main.m:677 - int x = { c0 00 00 00 }
/Users/rross/Documents/TestProj/TestProj/main.m:678 - short y = { 00 01 }
This requires ARC (and all of it's magic) enabled for any file you want to test this in, or you will manually have to release the __stack_ variables, which won't be pretty.
However, it now gives you a hex dump of the variable (rather than the weird pointer one), and if you really tried hard enough (using __builtin_types_compatible), it could detect whether the result was an object, and print that.
Once again, threads will mess this up, but a simple way to fix that would be to create a NSDictionary of NSArrays, with a NSThread as the key. Makes it a bit slower, but let's be honest, if you're using this over the C++ version, you aren't going for performance.

Why can I modify a const __restrict pointer but not a typdef'd version?

Note: I'm using the objective C compiler that ships with the latest version of Xcode.
Why is it that this is legal:
void verySpecial(const float* __restrict foo, const int size) {
for (int i = 0; i < size; ++i) {
// ... do special things ...
++foo; // <-- Should be illegal to modify const pointer?
}
}
However, if I use a typedef, it does what I think it should do.
typedef float* __restrict RFloatPtr;
void verySpecial(const RFloatPtr foo, const int size) {
for (int i = 0; i < size; ++i) {
// ... do special things ...
++foo; // <-- Now this is a compiler error.
}
}
So, what is different in the typedef'd case, and what don't I understand? Reading about __restrict makes my brain hurt, and I'm not even sure it matters here.
++foo; // <-- Should be illegal to modify const pointer?
Yap. Modifying a const pointer is illegal. However, modifying a non-const pointer to something which is const isn't. I think you're confusing
const float *foo
with
float *const foo
Also, of course you can't modify a restrict pointer, because it doesn't make sense. restrict tells the compiler that the pointer is guaranteed not to overlap with other pointers. This assumption may no longer be true if you decrement or increment the pointer.

What is the difference of the following const definition

Usually I use the first one to define const, but I don't know the difference of the following clearly.
static NSString* kFetcherCallbackThreadKey = #"_callbackThread";
static NSString* const kFetcherCallbackRunLoopModesKey = #"_runLoopModes";
NSString* const kFetcherRetryInvocationKey = #"_retryInvocation";
static const NSUInteger kMaxNumberOfNextLinksFollowed = 25;
In C, the static keyword, used outside a function, is used to declare a symbol that will be accessible only from the file in which it's declared. Kind of «private» global variables.
The const keyword means «constant». Read, the value can't be modified.
Note the two statements are different:
const int * x;
int * const x;
The first one defines a pointer to a constant integer (its value can't be modified, but it can point to something else).
The second one defines a constant pointer to an integer (the pointer value can't be modified, but the value of the int may be).
So you can perfectly have:
const int * const x;
So in your case:
static NSString* kFetcherCallbackThreadKey = #"_callbackThread";
A pointer to a NSString instance that will be accessible only from the file in which it's declared.
static NSString* const kFetcherCallbackRunLoopModesKey = #"_runLoopModes";
A constant pointer to a NSString instance that will be accessible only from the file in which it's declared.
NSString* const kFetcherRetryInvocationKey = #"_retryInvocation";
A constant pointer to a NSString instance that may be accessed from other files of your project.
static const NSUInteger kMaxNumberOfNextLinksFollowed = 25;
A constant integer that will be accessible only from the file in which it's declared.
static means that the variable is accessible only within the compilation unit it's declared in - essentially this source file. const means its value can never change. You can use one, both, or none depending on what you're looking for.
This is a static string which will be the same reference for all instances of the class (static). If you change it in one instance, it will change in all other instances.
static NSString* kFetcherCallbackThreadKey = #"_callbackThread";
This is an NSString pointer to a constant object that is also shared between all instances (static). The const directive makes the variable immutable.
static NSString* const kFetcherCallbackRunLoopModesKey = #"_runLoopModes";
This is a pointer to a constant NSString object. It could have a different instance for each class (if NSStrings are not interned by the compiler, I'm not sure if they are), but cannot be changed (const).
NSString* const kFetcherRetryInvocationKey = #"_retryInvocation";
This is a constant static integer. It will be shared between all instances of the class (static) and cannot be changed (const).
static const NSUInteger kMaxNumberOfNextLinksFollowed = 25;

Objective-C const NSString * vs NSString * const

I'm trying to a NSString constant in my .h file to be defined in my .m. I understand that
extern NSString * const variableName; in the .h and
NSString * const variableName = #"variableValue"; is the way to do this. Examining C tutorials I see that const is supposed to go before variable definitions. My question is why is it not declared as extern const NSString * variableName; in the .h and const NSString * variableName = #"variableValue"; in the .m. I know this doesn't work because I encounter compiler warnings which say 'Passing argument 1 of methodName: discards qualifiers from pointer target type'. What does this mean?
It's not the same. The const modifier can be applied to the value, or the pointer to the value.
int * const
A constant pointer (not modifiable) to an integer (its value can be modified)
const int *
A modifiable pointer to a constant integer (its value can't be modified)
So you can imagine:
const int * const;
Constant pointer is NOT a pointer to constant. Constant pointer means the pointer is constant. E.g. constant pointer int * const ptr2; indicates that ptr2 is a pointer which is constant. This means that ptr2 cannot be made to point to another integer. However, the integer pointed by ptr2 can be changed.
Whereas a pointer to constant const int * ptr1; indicates that ptr1 is a pointer that points to a constant integer. The integer is constant and cannot be changed. However, the pointer ptr1 can be made to point to some other integer.