设为首页 加入收藏

TOP

C语言的技巧知识(二)
2012-11-02 13:21:57 来源: 作者: 【 】 浏览:2193
Tags:语言 技巧 知识

    
    作为一种风格, 很多人不愿意在程序中到处出现未加修饰的0.因此定义了预处理宏NULL (在<stdio.h> 和其它几个头文件中) 为空指针常数, 通常是0 或者((void *)0)。希望区别整数0 和空指针0 的人可以在需要空指针的地方使用NULL.使用NULL 只是一种风格习惯; 预处理器把所有的NULL 都还原回0, 而编译还是依照上文的描述处理指针上下文的0.特别是, 在函数调用的参数里, NULL之前(正如在0 之前) 的类型转换还是需要。NULL 只能用作指针常数;
   
    其实对于空指针有两条潜在的的规则我们必须要明白:
   
    1、当你在源码中需要空指针常数时, 用“0” 或“NULL”.
   
    2、如果在函数调用中“0” 或“NULL” 用作参数, 把它转换成被调函数需要的指针类型
   
    7、数组和指针
   
    如果在一个源文件中定义了一个char a ,而在另一个源文件中声明了extern char *a,这样可以吗?
   
    试了一下,结果显示的是不行,在一个源文件中定义了一个字符串,而在另一个文件中定义了指向字符的指针,.extern char * 的申明不能和真正的定义匹配。类型T 的指针和类型T 的数组并非同种类型。应该使用extern char a[ ].
   
    那么char *a和char a[]是一样的么?
   
    并非如此。数组不是指针。数组定义char a 请求预留6 个字符的位置, 并用名称“a” 表示。也就是说, 有一个称为“a” 的位置, 可以放入6 个字符。而指针申明char *p, 请求一个位置放置一个指针, 用名称“p” 表示。这个指针几乎可以指向任何位置: 任何字符和任何连续的字符, 或者哪里也不指。
   
    如下面的语句所示:
   
    char a[] = “hello”;
   
    char *p = “world”;
   
    将会初始化下图所示的数据结果:
   
    +---+---+---+---+---+---+
   
    a: | h | e | l | l | o |\0 |
   
    +---+---+---+---+---+---+
   
    +-----+ +---+---+---+---+---+---+
   
    p: | *======> | w | o | r | l | d |\0 |
   
    +-----+ +---+---+---+---+---+---+
   
    根据x 是数组还是指针, 类似x 这样的引用会生成不同的代码。认识到这一点大有裨益。以上面的声明为例, 当编译器看到表达式a 的时候, 它生成代码从a 的位置开始跳过3 个, 然后取出那个字符。 如果它看到p , 它生成代码找到“p” 的位置, 取出其中的指针值, 在指针上加3 然后取出指向的字符。换言之, a 是名为a 的对象(的起始位置) 之后3 个位置的值, 而p 是p 指向的对象的3 个位置之后的值。在上例中, a 和p 碰巧都是‘l' , 但是编译器到达那里的途径不尽相同。本质的区别在于类似a 的数组和类似p 的指针一旦在表达式中出现就会按照不同的方法计算, 不论它们是否有下标。
   
    如此说来,那么在C语言中“数组和指针等价”到底是什么意思呢?
   
    在C 语言中对数组和指针的困惑多数都来自这句话。说数组和指针“等价”不表示它们相同, 甚至也不能互换。它的意思是说数组和指针的算法定义可以用指针方便的访问数组或者模拟数组。特别地, 等价的基础来自这个关键定义:
   
    一个T 的数组类型的左值如果出现在表达式中会蜕变为一个指向数组第一个成员的指针(除了三种例外情况); 结果指针的类型是T 的指针。这就是说, 一旦数组出现在表达式中, 编译器会隐式地生成一个指向数组第一个成员地指针, 就像程序员写出了&a[0] 一样。例外的情况是, 数组为sizeof 或&操作符的操作数,或者为字符数组的字符串初始值。作为这个这个定义的后果, 编译器并那么不严格区分数组下标操作符和指针
   
    在形如a[i] 的表达式中, 根据上边的规则, 数组蜕化为指针然后按照指针变量的方式如p[i] 那样寻址, 如问题6.2 所述, 尽管最终的内存访问并不一样。如果你把数组地址赋给指针:p = a;那么p 和a 将会访问同样的成员。
   
    那么数组和指针的区别是什么呢?
   
    数组自动分配空间, 但是不能重分配或改变大小。指针必须明确赋值以指向分配的空间(可能使用malloc), 但是可以随意重新赋值(即, 指向不同的对象), 同时除了表示一个内存块的基址之外, 还有许多其它的用途。
   
    8、为什么strncpy() 不能总在目标串放上终止符'\0'
   
    strncpy() 最初被设计为用来处理一种现在已经废弃的数据结构--定长, 不必'n0' 结束的“字符串”.strncpy 的另一个怪癖是它会用多个'n0' 填充短串, 直到达到指定的长度。在其它环境中使用strncpy() 有些麻烦, 因为你必须经常在目的串末尾手工加'n0'.可以用strncat 代替strncpy 来绕开这个问题: 如果目的串开始时为空(就是说, 如果你先*dest ='n0’), strncat() 就可以完成你希望strncpy() 完成的事情。另外一个方法是用sprintf(dest, “%.*s”, n, source)。如果需要复制任意字节(而不是字符串), memcpy() 是strncpy()更好的选择。
   
    怎样在C 程序中取得当前日期或时间?
   
    只要使用函数time(), ctime(), localtime() 和/或strftime() 就可以了。下面是个简单的例子:
   
    #include <stdio.h>
   
    #include <time.h>
   
    int main()
   
    {
   
    time_t now;
   
    time(&now);
   
    printf(“It's %s”, ctime(&now));
   
    return 0;
   
    }
   
    怎样获得在一定范围内的随机数?
   
    直接的方法是rand() % N /* 不好*/
   
    试图返回从0 到N 1 的数字。但这个方法不好, 因为许多随机数发生器的低位比特并不随机, 参见问题13.16.一个较好的方法是:
   
    (int)((double)rand() / ((double)RAND_MAX + 1) * N)
   
    如果你不希望使用浮点, 另一个方法是:
   
    rand() / (RAND_MAX / N + 1)
   
    两种方法都需要知道RAND_MAX, 而且假设N 要远远小于RAND MAX.RAND MAX 在ANSI 里#define 在<stdlib.h>.顺便提一下, RAND_MAX 是个常数, 它告诉你C 库函数rand() 的固定范围。你不可以设RAND MAX 为其它的值, 也没有办法要求rand() 返回其它范围的值。如果你用的随机数发生器返回的是0 到1 的浮点值, 要取得范围在0 到N-1内的整数, 只要将随机数乘以N 就可以了。

      

首页 上一页 1 2 3 4 5 6 7 下一页 尾页 2/8/8
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C语言内存池使用模型 下一篇C小程序 - 几个库函数

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: