参数未显式转换引起的栈问题

       近日编写项目源码时, 出现局部变量在调用函数接口前后变量值改变的问题. 经过再三调试, 才发现是传参问题. 此问题其实在编译时就会有警告信息, 不过没有加入该选项, 导致没有警告信息, 最终多个平台调试才发现问题所在.

        warning: 编译过程中一定要尽量加上警告选项.

        编译警告如下:

        27_implicitConversions.c:23: warning: passing argument 1 of ‘assignm’ from incompatible pointer type
        27_implicitConversions.c:4: note: expected ‘int *’ but argument is of type ‘short unsigned int *’
        27_implicitConversions.c:24: warning: passing argument 1 of ‘assignm’ from incompatible pointer type
        27_implicitConversions.c:4: note: expected ‘int *’ but argument is of type ‘short unsigned int *’
        27_implicitConversions.c:6: warning: dereferencing pointer ‘usNum1.17’ does break strict-aliasing rules
        27_implicitConversions.c:23: note: initialized from here
        27_implicitConversions.c:6: warning: dereferencing pointer ‘usNum2.18’ does break strict-aliasing rules
        27_implicitConversions.c:24: note: initialized from here

        错误原理分析:

        unsigned short 占16字节, int 占32字节.

        unsigned short 在函数中定义两个变量, 两个变量在栈中紧挨着. 分别是:

        0xbf9a558c

        0xbf9a558e

        196615 二进制: 0000 0000 0000 0011  0000 0000 0000 0111

        当赋值时, unsigned short = int; 短字节向长字节看齐. 此时unsigned short 变量1获得的值为:

        0000 0000 0000 0111. 十进制为: 7.

        unsigned short 变量2 再次赋值时, unsigned short 变量2获得的值依旧为:

        0000 0000 0000 0111. 十进制为: 7.

       但是由于没有强制转换, 而变量1和变量2在栈中是紧挨着的, 所以变量2在赋值时, 会把变量1所在的栈覆盖掉, 覆盖的为高位的16位, 即0000 0000 0000 0011. 所以变量2的值就变为3.

       抽象描述如下:

        196615 : 0000 0000 0000 0011 0000 0000 0000 0111

         变量1:                                        0000 0000 0000 0111

        196615:                                      0000 0000 0000 0011 0000 0000 0000 0111    

         变量2:                                                                            0000 0000 0000 0111

 

 

//源码

#include <stdio.h>
#include <stdlib.h>

int assignm(int *piNum)
{
    *piNum = 196615; //binary: 0000 0000 0000 0011  0000 0000 0000 0111

    return 0;
}

int main()
{
    unsigned short usNum1;
    char *pszStr1 = "Hello world";
    unsigned short usNum2;
    char *pszStr2 = "World peace";

    printf("%p\n", &usNum1);
    printf("%p\n", pszStr1);
    printf("%p\n", &usNum2);
    printf("%p\n", pszStr2);
    
    assignm(&usNum1);
    assignm(&usNum2);
    
    printf("usNum1 = %u\n", usNum1); 
    printf("pszStr1 = %s\n", pszStr1);
    printf("usNnum2 = %u\n", usNum2);
    printf("pszStr2 = %s\n", pszStr2);
    
    
    return 0;
}
 

/*运行结果:

0xbf9a558e
0x80486d0
0xbf9a558c
0x80486dc
usNum1 = 3                
pszStr1 = Hello world
usNnum2 = 7
pszStr2 = World peace
运行结果*/

 

转载于:https://my.oschina.net/u/1243181/blog/711698

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值