打印
[ARM入门]

C 陷阱与缺陷学习 笔记 —— 七、可移植性缺陷

[复制链接]
852|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
千岁寒|  楼主 | 2018-10-24 19:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  • C 标准与编译器的区别是关键!
  • 标识符名称的限制与区别
           有些C实现将所有字符作为有效字符;
           有些C自动截取长字符的尾部;
           ANSI标准规定,标识符可以为任意长度,但外部名必须至少能由前6个字符唯一地区分,并且不              区分大小写;
       例如:print_float   &   print_fileds    =====  可能带来为危险!
                  STATE  &   State  ===== 这样的命名方式不明智!

                    Malloc & malloc  ===== 可能导致不可预知的境地!

  • 整数的大小
                short  <  int  <  long        
                一个普通(int 类型)整数足够容纳任何数组下标

                字符长度有硬件特性决定 《大多数机器字符长度是8位》

  • 字符的符号
大多数计算机将8位字符当做8位整数处理,但是,并非所有编译器都按照8位整数来解释这些字符——这涉及符号位的解释与处理!当将一个字符转为较大(8Bit以上)整数时候,问题变得棘手!!!
        例如 :  char  -----> int 需要合理的处理掉符号位!!!   -128~127   VS   0~255

        例如 : char  c  直接使用(unsigned) c 是不能得到与c等价的无符号整数的!因为 其真实的转换过程是   -----    c >>> int >>> unsigned c

  • 移位运算符 (移位比除法快速)
1、向右移位,空出的位置由 0 还是 符号位の副本填充?
            无符号的一定用0填充;有符号的具体采用什么由C语言的具体实现决定!!!

2、移位计数(移位操作的位数)允许最大范围?
            必须严格控制的BIT_WIDTH以内!!!

3、向左移位,符号位符合处理,保留么?
  • 内存位置 0 (NULL)
NULL 只能不指向任何对象。因此除了赋值和比较运算,其他任何使用NULL指针的都是非法!!!
例如: strcmp(NULL,NULL) 是严重危险的
            --- 有的C对内存位置0做了硬件级的读保护,错误使用将立刻停止;

            --- 有的C对内存位置0只允许读;
            --- 有的C对内存位置0不做任何处理>>>>>>极端危险!!!!!

  • 触发运算时发生的截断
q  = a/b;
r   = a%b;
这里假设b!=0。
@1、q*b+r=a  余数关系约束条件;
@2、改变a的正负号,希望q跟着改变,但是q的绝对值不变;
@3、如果b>0, 希望r>=0 且 r<b ;
三个约束条件无法同时满足,一般的C实现选择支持1、2同时满足!!!
  • 随机数的大小
        早期的C在16位机器上实现随机函数rand(0~2^15-1非负整数)。后来的机器发展到32位,研发人员则实现了rand(0~2^31-1非负整数)。
        如此,则导致了移植的缺陷: 解决办法是提供了一个宏 RAND_MAX 来限定最大随机数!!!

  • 大小写转换
        早期的库函数 toupper  和  tolower 被定义为宏

#define toupper(c)   ( (c) + 'A' - 'a' )
#define tolower(c)   ( (c)  + 'a' - 'A' )
危险之处在于如果c 传入的大小写不对!!!就会返回无效信息!!!
因此一般用法: (  isupper(c)?tolower(c):c  )
        

        为了避免,每次都预先检测,进一步的改进是:

#define toupper(c)   ( (c) >= ‘a’&&  (c) <= 'z'  ?  (c) + 'A' - 'a' : (c) )
#define tolower(c)    ( (c) >= 'A' && (c) <= 'Z' ?  (c) + 'a' - 'A' : (c)  )
        但是: 如果 使用 toupper(*p++)这样又会带来重复计算的危险!!!



        最终,采用了两种实现方式,以便于灵活实现:

int toupper(int c)
{
    if(c>='a' && c<='z')

            return c+'A'-'a'

    return c;

}
#define _toupper(c)   ( (c) + 'A' - 'a' )


tolowper 也 有类似实现!
  • 首先释放而后重新分配
malloc  realloc  free
realloc :  该函数指针 ptr 所指向内存的大小调整为size字节,返回一个指向调整后内存块(可能改内存块已经被移动过了)的指针。
            假定原来是 oldsize  新的是 newsize, 那么min(oldsize,newsize)中的内容保持不变!!!

相关帖子

沙发
caijie001| | 2018-10-25 00:23 | 只看该作者
牛X

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

72

主题

244

帖子

4

粉丝