使用JNI时遇到问题。
jboolean z = (jboolean) NULL; // ok
jbyte b = (jbyte) NULL; // ok
jchar c = (jchar) NULL; // ok
jshort s = (jshort) NULL; // ok
jint i = (jint) NULL; // ok
jlong j = (jlong) NULL; // ok
jobject l = (jobjec) NULL; // ok
jfloat f = (jlong) NULL; // NOT OK
jdouble d = (jdouble) NULL; // NOT OK
编译器抱怨
[ERROR] /....c:112:28: error: pointer cannot be cast to type 'jfloat' (aka 'float')
[ERROR] jfloat result = (jfloat) NULL;
[ERROR] ^~~~
[ERROR] /usr/include/sys/_types/_null.h:29:15: note: expanded from macro 'NULL'
[ERROR] #define NULL __DARWIN_NULL
[ERROR] ^~~~~~~~~~~~~
[ERROR] /usr/include/sys/_types.h:52:23: note: expanded from macro '__DARWIN_NULL'
[ERROR] #define __DARWIN_NULL ((void *)0)
[ERROR] ^~~~~~~~~~~
[ERROR] 1 error generated.
我该如何解决这个问题?
我正在为每个值编写方法。
jboolean doSome() {
jboolean result = (jboolean) NULL;
/*
* at here result may be initialized or remain as NULL
*/
return result;
}
我打算写一个函数结合以下三种方法。
(*env)->GetObjecClass(JNIEnv *, jobject);
(*env)->GetMethodID(JNIEnv *, jclass, char *, char *);
(*env)->CallBooleanMethodA(JNIEnv *, jclass, jmethodID, jvalue *);
像这样。
jboolean CallBooleanMethodAMmMs(JNIEnv * env, jobject obj, char * mname,
char * msig, jvalue * args) {
jboolean result = (jboolean) NULL;
jclass clazz = (*env)->GetObjectClass(env, obj);
jmethodID methodID = (*env)->GetMethodID(env, clazz, mname, msig);
if (methodID != NULL) {
result = (*env)->CallBooleanMethodA(env, obj, methodID, args);
}
(*env)->DeleteLocalRef(env, clazz);
return result;
}
我认为我可以使用NULL
来处理任何不成功的情况,例如methodID == NULL
。
我想我应该使用jobject
而不是原语,对吧?
答案 0 :(得分:4)
您不能(也不应该)将指针分配给普通变量。
我真的不知道为什么它允许其他一些正常的数据类型,正如你所提到的那样。对于从指向其他非指针数据类型的指针的所有赋值,编译器应该同样产生相同的警告
NULL
是stdio.h中定义的void指针,用于初始化指针类型变量。如果要初始化非指针变量,请使用简单的0
代替NULL
。
答案 1 :(得分:3)
NULL
应该用作指针的特殊值。这是Option Types的替代(在其他语言中使用,通常被认为是更好的解决方案)并且仅适用于指针类型(因为对于其他类型,它更容易选择一个值作为值用那个"特殊含义")。
所以NULL
的处理方式与任何其他指针的处理方式相同。虽然指针转换为整数类型在某些特殊情况下仍然有意义(即使它很危险,因为根据类型你可能会截断指针),将它转换为指针肯定没有任何意义。一个浮点数(它们用于数值计算,对内存地址没有意义)。
无论如何,你想要实现什么目标?如果只是将这些变量初始化为明确定义的初始值,请尝试0.0f
和0.0
而不是NULL
。
答案 2 :(得分:2)
如何将NULL分配给float / double变量?
使用intptr_t/uintptr_t
这些整数类型可以保存void *
的信息。
这将保留再次void *
所需的信息,与NULL
平等对比。
intptr_t iptr = (intptr_t) NULL;
void *ptr = (void *) iptr;
assert(ptr == NULL);
这会将整数转换为double
,但信息(例如精度)可能会丢失。如果代码尝试转换回intptr_t
,然后void *
,然后尝试与NULL
进行同等比较,则可能会失败。
intptr_t iptr = (intptr_t) NULL;
double fp = (double) iptr;
intptr_t iptr2 = (intptr_t) fp;
void *ptr = (void *) iptr2;
// May not succeed
assert(ptr == NULL);