- 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、向左移位,符号位符合处理,保留么?
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)中的内容保持不变!!!
|