C单元转换的问题

C单元转换的问题,c,type-conversion,unsigned,C,Type Conversion,Unsigned,我目前正在开发一个Android应用程序,它使用本机C库。我对C非常不熟悉,并且有一些转换问题。我知道这个问题与有符号/无符号数字有关,但我不知道我需要做什么来解决这个问题 C库本身运行良好,并产生正确的结果。然而,当我把它移植回Android时,只有正值是正确的。负值返回为256减去该值 例如: 8 -> 8 5 -> 5 1 -> 1 0 -> 0 -3 -> 253 -5 -> 251 -8 -> 248 这是C代码赋值时的样子: BYT

我目前正在开发一个
Android
应用程序,它使用
本机C库。
我对C非常不熟悉,并且有一些转换问题。我知道这个问题与有符号/无符号数字有关,但我不知道我需要做什么来解决这个问题

C库本身运行良好,并产生正确的结果。然而,当我把它移植回Android时,只有正值是正确的。负值返回为256减去该值

例如:

 8 -> 8
 5 -> 5
 1 -> 1
 0 -> 0
-3 -> 253
-5 -> 251
-8 -> 248
这是C代码赋值时的样子:

BYTE *parms;
WORD __stdcall GetValue(BYTE what, long *val){

    char myStringParmsOne[255];
    sprintf( myStringParmsOne, "parms[1]=%d", parms[1] );
    LOG_INFO( myStringParmsOne );

    char myStringIsG[255];
    sprintf( myStringIsG, "API_isG=%d",API_isG );
    LOG_INFO( myStringIsG );

    char myStringCharParmsB[255];
    sprintf( myStringCharParmsB, "(char)parms[1]=%d", (char)parms[1] );
    LOG_INFO( myStringCharParmsB );

    *val=(char)parms[1]-(API_isG?11:0);
}
LOG\u INFO
语句将值打印到
LogCat
。下面是程序运行时的值,预期值为
-3

The first **parms[1]=%d** statement returns **parms[1]=253**

The second **API_isG=%d** statement returns **API_isG=0**

The third **(char)parms[1]=%d** statement returns **(char)parms[1]=253**
字节和字类型定义如下:

typedef unsigned char BYTE;
typedef unsigned short WORD;
我用于将此值发送回Java的包装函数如下所示:

long Java_my_package_Model_00024NativeCalls_GetValueJava( JNIEnv *env, jobject obj, WORD what) {
    long c;
    int j = GetValue( what, &c );
    if( j == 0 ) {
        return c;
    } else {
        return -1;
    }
}
编辑

GetValue
方法一直都在使用,但只有这个单独的调用会给我带来负数问题,它适用于其他调用。我已经为包装器函数尝试了以下两种方法:

long Java_my_package_Model_00024NativeCalls_GetValueJava( JNIEnv *env, jobject obj, WORD what) {
    long c;
    int j = GetValue( what, &c );
    if( j == 0 ) {
        return (signed char)c;
    } else {
        return -1;
    }
}
上面返回值的转换为我提供了一个合适的返回值。但是,对其他值调用此函数的所有其他调用都是完全混乱的

long Java_my_package_Model_00024NativeCalls_GetValueJava( JNIEnv *env, jobject obj, WORD what) {
    long c;
    int j = GetValue( what, &c );
    if( j == 0 ) {
        return (signed long)c;
    } else {
        return -1;
    }
}

上面对返回值的强制转换没有改变任何内容。

如果要存储有符号的值,请将类型从unsigned char/unsigned short更改为char/short。

发生这种情况是因为您将无符号字符(NDK char中的IIRC默认为unsigned)放在长字符串中。如果在long中输入的值是有符号的,那么编译器也会更改long的符号位

尝试将演员阵容从

*val=(char)parms[1]-(API_isG?11:0);


(不确定是否需要(长)转换,可能是转换为(签名字符)这就足够了。

这是因为
字节
是无符号的,并且硬件使用了负数的两个互补表示。您能告诉我们构建应用程序的硬件体系结构是什么吗?@mathk它是定制的,在公开市场上没有可用的。应该是
有符号字符
,因为它是实现定义的,如果
char
是有符号的还是无符号的。我无法更改
BYTE/WORD
类型,它们到处都在使用。正在使用的C库也用于Palm Pilot程序,它工作得非常好。这就是为什么我相信它与将值移植回Android有关。有没有办法转换va包装器函数中的lue?我不确定它是否有助于OP,因为发生了强制转换:
*val=(char)parms[1]-(API_isG?11:0)
我的直觉是,在C语言中的long和Java语言中的long之间在包装器级别存在混淆。char是按定义签名的,这里不需要签名。谢谢,这有助于修复我遇到的参数问题,但现在其他一些参数的行为很有趣。这可能是完全不相关的事情,但我在回家之前不会知道今晚检查。明天我肯定会接受答案。@mathk:在C中不是真的。在C中,由编译器决定
char
是有符号的还是无符号的。如果需要签名
char
,则需要显式声明类型为
signed char
*val=(long)((signed char)parms[1]-(API_isG?11:0));