【问题标题】:Trouble with C unit conversionC单位转换问题
【发布时间】:2013-07-25 15:56:49
【问题描述】:

我目前正在开发一个使用native C library.Android 应用程序我对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_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**

BYTE 和 WORD 类型定义如下:

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;
    }
}

上面的返回值转换没有改变。

【问题讨论】:

  • 那是因为BYTE 是无符号的,并且硬件使用二进制补码表示负数。
  • 您能说出我们为哪种硬件架构构建您的应用程序吗?
  • @mathk 这是定制的,在公开市场上没有任何东西。

标签: c type-conversion unsigned


【解决方案1】:

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

尝试更改演员表

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

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

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

【讨论】:

  • char 是按定义签名的,这里不需要签名。
  • 谢谢,这有助于解决我遇到问题的参数,但现在其他一些人的行为很有趣。这可能是完全不相关的事情,但直到今晚我回家检查才知道。明天我肯定会接受答案。
  • @mathk:在 C 语言中不正确。
  • 在 C 中,由编译器决定 char 是有符号还是无符号。如果需要对char进行签名,则需要将类型显式声明为signed char
【解决方案2】:

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

【讨论】:

  • 应该是signed char,因为如果char是有符号或无符号,它是实现定义的。
  • 我无法更改 BYTE/WORD 类型,它们到处都在使用。正在使用的 C 库也用于 Palm Pilot 程序,该程序运行良好。这就是为什么我认为这与将价值移植回 Android 有关。有没有办法可以转换包装函数中的值?
  • 我不确定它是否会对 OP 有所帮助,因为正在发生演员阵容:*val=(char)parms[1]-(API_isG?11:0); 我的直觉是,在 C 中的 long 和 Java 中的 long 之间的包装级别存在混淆。
猜你喜欢
  • 2011-11-05
  • 2013-11-17
  • 2016-11-27
  • 2011-04-13
  • 1970-01-01
  • 1970-01-01
  • 2020-09-26
相关资源
最近更新 更多