改变static值,但还是取到原来的值的原因解答

本文探讨了Android中Service间通过Static变量进行通信时遇到的问题,即在一个Service修改Static变量后,另一个Service未能读取到更新后的值。文章分析了可能的原因,并提供了验证方法。

问题描述:

1.android中,Service与Activity,或者Service与Service等的通信中,使用到static静态对象,在一个Service改变了值却在另外一个Service中却发现值没改变

例子:http://www.apkbus.com/forum.php?mod=viewthread&tid=140090&extra=page%3D1&page=2

简单说 : static静态对象在改变值后当再次getValue时发现值还是原来的值。



原因可能:

1.要么就是同步锁问题,static默认是线程不安全
2. 两次调用的不在同一个进程里面(没错就是进程)


深入分析:

1.为了验证是否是不同进程,可以在调用的地方输出查看进程,获得进程id(name)的方法如下:
        (1)java  :  ManagementFactory.getRuntimeMXBean().getName()  ,@之前的就是id
        (2)android : android.os.Process.myPid()
2.查看AndroidManifest.xml中是否有android:process,查看是否创建了新的进程
        (1)android:process=":remote",代表在应用程序里,当需要该service时,会自动创建新的进程。
        (2)android:process="remote",没有“:”分号的,则创建全局进程,不同的应用程序共享该进程。
3. 如果真的是不同进程,那么就是不同的static静态对象,自然也就不会改变对方的值。


<think>我们有两个问题需要解决:1.理解uint8_t(0x80)的是多少?2.之前关于uint8_taddr[3]初始化时出现错误的原因(MISRAC违规)是什么?首先,我们先解决第一个问题:uint8_t(0x80)的。在C语言中,uint8_t是一个无符号8位整数类型,它的取范围是0到255(即$0$到$2^8-1$)。0x80是一个十六进制常量,相当于二进制的10000000,十进制为128。当我们使用强制类型转换将0x80转换为uint8_t时,由于0x80在uint8_t的表示范围内(128<=255),所以转换后的就是128。但是,这里有一个需要注意的地方:如果0x80被解释为有符号的整数(例如,在一些系统中,0x80如果被当作char类型可能是负数),那么直接赋给无符号类型会发生转换。然而,在C语言中,整型常量0x80的类型是int(因为它是十六进制整数,且没有后缀,所以是int类型,而int类型至少是16位,因此0x80(即128)在int的范围内,所以它是一个正的int)。因此,转换为uint8_t就是128。所以,uint8_t(0x80)的是128。接下来,我们回顾之前的问题:为什么初始化数组会报错?之前的问题代码:uint8_taddr[3]={RESET_ADDR0,RESET_ADDR1,RESET_ADDR2};报错的原因是违反了MISRAC-2004Rule10.1:表达式的不应隐式转换为不同的基本类型。具体来说,RESET_ADDR0等宏定义可能是整型常量(比如0x80),而整型常量(如0x80)的类型是int(有符号整数),而数组元素的类型是uint8_t(无符号8位整数)。在初始化时,将int类型的赋给uint8_t类型的变量,会发生隐式类型转换,这种转换改变了符号性(从有符号到无符号),因此违反了MISRA规则。解决方案是使用显式类型转换,例如:uint8_taddr[3]={(uint8_t)RESET_ADDR0,(uint8_t)RESET_ADDR1,(uint8_t)RESET_ADDR2};这样,我们就明确地进行了转换,告诉编译器我们是有意为之,从而避免了隐式转换的违规。另外,引用[1]中的例子也说明了类似的问题:typedefenum{Bit_RESET=1,Bit_SET=2}BitAction;uint8_tdata;uint8_tValue=0x80;data=(BitAction)Value;这里,Value是0x80(即128),然后强制转换为枚举类型BitAction。枚举类型BitAction实际上只有两个(1和2),而128超出了枚举定义的范围。这种转换在C语言中是允许的,但它的是多少呢?实际上,枚举类型在C中就是整数类型,所以data的就是128。但是,这个不是枚举中定义的有效(Bit_RESET或Bit_SET),所以使用这个可能会导致未定义的行为(如果期望只有1或2)。所以,在编程时,我们应该避免将超出枚举范围的赋给枚举变量。总结:1.uint8_t(0x80)的是128。2.初始化数组报错是因为隐式类型转换(有符号整数到无符号整数)违反了MISRA规则,需要显式转换。最后,我们生成相关问题:§§相关问题§§1.如何安全地将超出枚举范围的转换为枚举类型?2.在C语言中,整型常量的默认类型是什么?3.除了显式类型转换,还有其他方法避免MISRAC-2004Rule10.1违规吗?4.为什么MISRAC规则要禁止隐式类型转换?</think>### 解答:`uint8_t(0x80)`的与数组初始化报错原因 #### 1. `uint8_t(0x80)`的解析 在C语言中: ```c uint8_t value = 0x80; // 十六进制赋 ``` - **二进制表示**: `0x80` → `1000 0000`(8位二进制) - **十进制**: 按无符号整数解释:$128$ 按有符号整数解释:$-128$(补码表示) - **实际存储**: 由于 `uint8_t` 是**无符号类型**,实际存储为 $128$ 验证代码: ```c printf("%u", value); // 输出 128 ``` > **关键区别**: > 若用 `int8_t`(有符号)存储 `0x80`,会是 $-128$,但 `uint8_t` 始终解释为 $0$ 到 $255$ 的无符号[^1]。 #### 2. 数组初始化报错原因 ##### 错误代码: ```c uint8_t addr[3] = {RESET_ADDR0, RESET_ADDR1, RESET_ADDR2}; // 报错 ``` ##### 根本原因: 1. **符号性不匹配** - `uint8_t`:显式无符号类型(范围 $0$ 到 $255$) - `RESET_ADDRx` 宏:通常定义为整数字面量(如 `#define RESET_ADDR0 0x80`) - 整数字面量默认是 **`int` 类型(有符号)** 2. **违反 MISRA C Rule 10.1** > "表达式的不应隐式转换为不同的基本类型" > —— 尤其禁止 **隐式符号性转换**(有符号 ↔ 无符号) 3. **风险示例** 若 `RESET_ADDR0` 定义为负数(如 `-1`): ```c #define RESET_ADDR0 -1 // 有符号int uint8_t addr = RESET_ADDR0; // 隐式转为 255 ``` - 实际地址计算:$ \text{基地址} + 255 \times \text{偏移} $ → **严重内存错误**[^3] #### 3. 解决方案(MISRA 合规) ##### 方法1:显式强制转换(推荐) ```c uint8_t addr[3] = { (uint8_t)RESET_ADDR0, // 显式声明意图 (uint8_t)RESET_ADDR1, (uint8_t)RESET_ADDR2 }; ``` ##### 方法2:定义无符号宏 ```c // 原定义(有问题) #define RESET_ADDR0 0x80 // 默认有符号int // 修复定义 #define RESET_ADDR0 ((uint8_t)0x80) // 显式无符号 #define RESET_ADDR1 UINT8_C(0x81) // C99标准无符号常量 ``` ##### 方法3:静态断言验证 ```c #include <assert.h> static_assert(RESET_ADDR0 <= UINT8_MAX, "Address overflow!"); uint8_t addr[3] = {RESET_ADDR0, RESET_ADDR1, RESET_ADDR2}; ``` #### 关键验证实验 ```c #include <stdio.h> #include <stdint.h> #define TEST_ADDR 0x80 int main() { uint8_t a = TEST_ADDR; // 隐式转换(违规) uint8_t b = (uint8_t)TEST_ADDR; // 显式转换(合规) printf("隐式转换: %u\n", a); // 输出 128 printf("显式转换: %u\n", b); // 输出 128 return 0; } ``` > 输出相同,但显式转换满足安全规范[^1]。 ### 总结表 | **场景** | **风险** | **合规方案** | |----------|----------|--------------| | 有符号→无符号隐式转换 | 域错误(如 -1→255) | 显式强制转换 `(uint8_t)` | | 宏定义整数字面量 | 默认有符号类型 | 用 `UINT8_C()` 或 `(uint8_t)` 包装 | | 数组初始化 | MISRA Rule 10.1 违规 | 每个元素显式转换 |
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值