问题
Yesterday, I updated Xcode to the newest version (5.1 (5B130a))
to compatible with iOS 7.1
. Then I build my project, I get the error "Cast from pointer to smaller type 'int' loses information"
in EAGLView.mm
file (line 408
) when 64-bit simulators (e.g.: iPhone Retina 4-inch 64-bit) is selected.
I'm using cocos2d-x-2.2.2
. Before I update Xcode, my project still can build and run normally with all devices.
Thanks for all recommendation.
Update: Today, i download the latest version of cocos2d-x (cocos2d-x 2.2.3). But the problem has still happened.
Here is some piece of code where that error occur:
/cocos2d-x-2.2.2/cocos2dx/platform/ios/EAGLView.mm:408:18: Cast from pointer to smaller type 'int' loses information
// Pass the touches to the superview
#pragma mark EAGLView - Touch Delegate
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if (isKeyboardShown_)
{
[self handleTouchesAfterKeyboardShow];
return;
}
int ids[IOS_MAX_TOUCHES_COUNT] = {0};
float xs[IOS_MAX_TOUCHES_COUNT] = {0.0f};
float ys[IOS_MAX_TOUCHES_COUNT] = {0.0f};
int i = 0;
for (UITouch *touch in touches) {
ids[i] = (int)touch; // error occur here
xs[i] = [touch locationInView: [touch view]].x * view.contentScaleFactor;;
ys[i] = [touch locationInView: [touch view]].y * view.contentScaleFactor;;
++i;
}
cocos2d::CCEGLView::sharedOpenGLView()->handleTouchesBegin(i, ids, xs, ys);
}
回答1:
Apparently the clang version in Xcode 5.1 and above is more strict about potential 32bit vs. 64 bit incompatibilities in source code than older clang versions have been. To be honest, I think, clang is too restrictive here. A sane compiler may throw a warning on lines like this but by no way it should throw an error, because this code is NOT wrong, it is just potentially error-prone, but can be perfectly valid.
The original code is
ids[i] = (int)touch;
with ids being an array of ints and touch being a pointer.
In a 64bit build a pointer is 64bit (contrary to a 32bit build, where it is 32bit), while an int is 32bit, so this assignment stores a 64bit value in a 32bit storage, which may result in a loss of information.
Therefore it is perfectly valid for the compiler to throw an error for a line like
ids[i] = touch;
However the actual code in question contains an explicit c-style cast to int. This explicit cast clearly tells the compiler "Shut up, I know that this code does not look correct, but I do know what I am doing".
So the compiler is very picky here and the correct solution to make the code compile again and still let it show the exact same behavior like in Xcode 5.0 is to first cast to an integer type with a size that matches the one of a pointer and to then do a second cast to the int that we actually want:
ids[i] = (int)(size_t)touch;
I am using size_t here, because it is always having the same size as a pointer, no matter the platform. A long long would not work for 32bit systems and a long would not work for 64 bit Windows (while 64bit Unix and Unix-like systems like OS X use the LP64 data model, in which a long is 64bit, 64bit Windows uses the LLP64 data model, in which a long has a size of 32bit (http://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models)).
回答2:
Replace this ids[i] = (int)touch;
with ids[i] = (uintptr_t)touch;
It works for me.
回答3:
I meet this problem too.
ids[i] = (int)touch;
// error occur here => I change this to below.
ids[i] = (uintptr_t)touch;
Then i can continue compiling. Maybe you can try this too.
回答4:
you can use uintptr_t instead of int. its standard followed by Xcode.
回答5:
XCode 5.1 is change all architecture to 64 bit.
you can just change architecture to support 32 bit compilation by all below in in Build Settings
- use $(ARCHS_STANDARD_32_BIT) at Architecture instead of $(ARCHS_STANDARD)
- remove arm64 at Valid Architectures
Hope it helps.
回答6:
Surely the solution is to change the type of ids from int to type that is sufficiently large to hold a pointer.
I'm unfamiliar with XCode, but the solution should be something like follows:
Change the declaration of ids to:
intptr_t ids[IOS_MAX_TOUCHES_COUNT];
and the line producing the error to:
ids[i] = (intptr_t)touch;
Most of the "solutions" above can lose part of the pointer address when casting to a smaller type. If the value is ever used as pointer again that will prove to be an extremely bad idea.
回答7:
You can fix this error by replacing this line of code.
ids[i] = (uint64_t)touch;
You should perform type conversion based on 64bit build system because the type "int" supports only -32768 ~ 32768.
回答8:
ids[i] = (int)touch; put * and check it.
ids[i] = *(int *)touch;
来源:https://stackoverflow.com/questions/22419063/error-cast-from-pointer-to-smaller-type-int-loses-information-in-eaglview-mm