一个强制转换引发的血案及反思

时间:2022-09-20 07:30:18

  首先看一个C语言的例子:

一个强制转换引发的血案及反思一个强制转换引发的血案及反思
#include <stdio.h>
#include <string.h>
#include <assert.h>


typedef short uint16_t;
typedef int uint32_t;

void audio_mono2stereo_16bits(uint16_t *dst_buf, uint16_t *src_buf, uint32_t src_len)
{
    uint32_t i = 0;
    for (i = 0; i < src_len; ++i) {
        dst_buf[i*2 + 0] = dst_buf[i*2 + 1] = src_buf[i]>>1;
    }
}

void audio_stereo2mono_16bits(unsigned char channel, uint16_t *dst_buf, uint16_t *src_buf, uint32_t src_len)
{
    uint32_t i = 0;
    for (i = 0; i < src_len; i+=2) {
        dst_buf[i/2] = src_buf[i + channel];
    }
}

void audio_stereo2mono_16bits_check(unsigned char channel, int *dst_buf, int *src_buf, uint32_t src_len)
{
    uint32_t i = 0;
    for (i = 0; i < src_len; i+=2) {
        dst_buf[i/2] = src_buf[i + channel];
    }
}

#define BUFF_SIZEA 160

static int iarray[BUFF_SIZEA];
static int oarray[2*BUFF_SIZEA];

void dump16(short *ibuf, int length)
{
  int j = 0;

  for (j=0; j<length; j++) {
   //if (!(j%20)) printf("%d == ",j);
   printf(" %d, ", ibuf[j]);
   if (!((j+1)%10)) printf("\n");
 }
}
int main()
{
        int ibuff[160],outbuf[160];
        int ilen = BUFF_SIZEA;
        for(int icnt = 0; icnt < BUFF_SIZEA; icnt++)
        {
                iarray[icnt] = -icnt;
        }

        audio_stereo2mono_16bits(0,oarray,iarray,BUFF_SIZEA);
        printf("input data.........................................\n");
        dump16(iarray,30);
        printf("output data.........................................\n");
        dump16(oarray,30);
        audio_stereo2mono_16bits_check(0,oarray,iarray,BUFF_SIZEA);
        //audio_mono2stereo_16bits(oarray,iarray,30);
        printf("output data2.........................................\n");
        dump16(oarray,30);

        return 0;
}
View Code

  运行结果:

input data.........................................
 0,  0,  -1,  -1,  -2,  -1,  -3,  -1,  -4,  -1, 
 -5,  -1,  -6,  -1,  -7,  -1,  -8,  -1,  -9,  -1, 
 -10,  -1,  -11,  -1,  -12,  -1,  -13,  -1,  -14,  -1, 
output data.........................................
 0,  -1,  -2,  -3,  -4,  -5,  -6,  -7,  -8,  -9, 
 -10,  -11,  -12,  -13,  -14,  -15,  -16,  -17,  -18,  -19, 
 -20,  -21,  -22,  -23,  -24,  -25,  -26,  -27,  -28,  -29, 
output data2.........................................
 0,  0,  -2,  -1,  -4,  -1,  -6,  -1,  -8,  -1, 
 -10,  -1,  -12,  -1,  -14,  -1,  -16,  -1,  -18,  -1, 
 -20,  -1,  -22,  -1,  -24,  -1,  -26,  -1,  -28,  -1,

  是不是运行结果很乱?是哪儿出问题了呢?

  接下来再看另外一个例子:

一个强制转换引发的血案及反思一个强制转换引发的血案及反思
 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <assert.h>
 4 
 5 
 6 typedef short uint16_t;
 7 typedef int uint32_t;
 8 
 9 void audio_mono2stereo_16bits(uint16_t *dst_buf, uint16_t *src_buf, uint32_t src_len)
10 {
11     uint32_t i = 0;
12     for (i = 0; i < src_len; ++i) {
13         dst_buf[i*2 + 0] = dst_buf[i*2 + 1] = src_buf[i]>>1;
14     }
15 }
16 
17 void audio_stereo2mono_16bits(unsigned char channel, uint16_t *dst_buf, uint16_t *src_buf, uint32_t src_len)
18 {
19     uint32_t i = 0;
20     for (i = 0; i < src_len; i+=2) {
21         dst_buf[i/2] = src_buf[i + channel];
22     }
23 }
24 
25 void audio_stereo2mono_16bits_check(unsigned char channel, int *dst_buf, int *src_buf, uint32_t src_len)
26 {
27     uint32_t i = 0;
28     for (i = 0; i < src_len; i+=2) {
29         dst_buf[i/2] = src_buf[i + channel];
30     }
31 }
32 
33 #define BUFF_SIZEA 160
34 
35 static short iarray[BUFF_SIZEA];
36 static short oarray[2*BUFF_SIZEA];
37 
38 void dump16(short *ibuf, int length)
39 {
40   int j = 0;
41 
42   for (j=0; j<length; j++) {
43    //if (!(j%20)) printf("%d == ",j);
44    printf(" %d, ", ibuf[j]);
45    if (!((j+1)%10)) printf("\n");
46  }
47 }
48 int main()
49 {
50         int ibuff[160],outbuf[160];
51         int ilen = BUFF_SIZEA;
52         for(int icnt = 0; icnt < BUFF_SIZEA; icnt++)
53         {
54                 iarray[icnt] = -icnt;
55         }
56 
57         audio_stereo2mono_16bits(0,oarray,iarray,BUFF_SIZEA);
58         printf("input data.........................................\n");
59         dump16(iarray,30);
60         printf("output data.........................................\n");
61         dump16(oarray,30);
62         audio_stereo2mono_16bits_check(0,oarray,iarray,BUFF_SIZEA);
63         //audio_mono2stereo_16bits(oarray,iarray,30);
64         printf("output data2.........................................\n");
65         dump16(oarray,30);
66 
67         return 0;
68 }
View Code

  运行结果:

input data.........................................
 0,  -1,  -2,  -3,  -4,  -5,  -6,  -7,  -8,  -9, 
 -10,  -11,  -12,  -13,  -14,  -15,  -16,  -17,  -18,  -19, 
 -20,  -21,  -22,  -23,  -24,  -25,  -26,  -27,  -28,  -29, 
output data.........................................
 0,  -2,  -4,  -6,  -8,  -10,  -12,  -14,  -16,  -18, 
 -20,  -22,  -24,  -26,  -28,  -30,  -32,  -34,  -36,  -38, 
 -40,  -42,  -44,  -46,  -48,  -50,  -52,  -54,  -56,  -58, 
output data2.........................................
 0,  -1,  -4,  -5,  -8,  -9,  -12,  -13,  -16,  -17, 
 -20,  -21,  -24,  -25,  -28,  -29,  -32,  -33,  -36,  -37, 
 -40,  -41,  -44,  -45,  -48,  -49,  -52,  -53,  -56,  -57, 

  其实,这两个例子说明了很多问题,也让我在一个很大型的程序中,花费了不少时间去定位这个输出的数据一直不正确的问题.其实,核心的问题,就是我把short类型和int类型之间强制转换的过程中出现了问题.

不同类型之间的强制转换,在这个知识点掌握不够透彻的情况下,就一头栽倒在这个深坑中出不去了.当我花费很大力气去解决这个bug,必须要应该回头反思一下了.

  用了那么多年的C语言,我真的掌握了吗?

  像很多初级程序员一样,在我拿出去的简历上,经常会用黑体标出来---熟练掌握C语言.在一般的面试中,也能够应付面试官,在日常的工作中,绝大多数的代码也能够看懂,也能够实现所需的功能.这样,我就飘飘然了,以为自己已经掌握了C语言,当到了实战中,才发现很多东西远远还没有达到理解的境界.

  每天都是用的东西,为什么还犯这种低级的错误?

  就像每天见到的同事,假如你没有和他有很深业务上的往来或者利益冲突,是根本无法看清楚这个人的.工作中用的语言也是同样的情况,很多时候,我们都喜欢使用熟悉的套路去写程序,自己不熟悉还有不了解的东西一般是不会使用的,这样就出现了,熟的愈加熟练,陌生的依旧是陌生.这,也许就是人性吧.

  今后的应对策略.  

  其实,这个是有解决方法的.根据经验,以后要针对这些情况,做以下功课吧.

  定期总结,针对不熟悉的模块和知识,要定期的去总结.

  经典的书籍要反复看,特别是相关的经典书籍,千万不能看一遍就丢了.

  多看优秀的源码,特别是内核的源码,经典的一定要反复去看,今后,要找个时间熟悉和分析一下linux内核源码.并写一个专题.