zoukankan      html  css  js  c++  java
  • [C程序设计语言]第四部分

     

    结构体


    struct point {
        intx;
        inty;
    } x, y;
     
    关键字struct后面的point可以省略,它是结构标记。结构标记用于为结构命名,在定义之后,结构标记就代表花括号内的声明,可以用它作为该声明的简写形式,并可以用在后面的结构体声明语句中
     
    如果结构声明的后面不带变量表(这里为x y),则不需要为它分配存储空间,它仅仅描述了一个结构的模板或轮廓。但是,如果结构声明中带有标记,那么在以后定义结构实例时便可以使用该标记定义:
    struct point z;
     
    结构体初始化只能是常量表达式:
    struct point maxpt={320,200}
     
    访问结构体成员:maxpt.x
     
    结构体可以嵌套。
     
    结构体参数传递时是按值传递
     
    如果传递给函数的结构体很大,使用指针方式的效率通常比复制整个结构的效率要高。结构体指针类似于普通变量指针:
    struct point *pp=&maxpt;
    (*pp).x = 3;
    圆括号是必需的,因为结构成员运算符“.”的优先级比“*”的优先级要高
    结构指针的使用上频度非常高,为了使用方便,C语言提供了另一种简写方式,假定P是一个指向结构的指针,可以用p->结构成员 这种形式引用相应结构成员。
     
    运算符“.”和“->”都是从左至右结合的
     
    在所有运算符中,下面4个运算符的优先级最高:结构运算符“.”和“->”、用于函数调用的“()”以及用于下标“[]”:++p->len相当于++(p->len),可以使用括号改变其运算结合顺序,如(++p)->len,但(p++)->len则还是先对len执行操作,然后再将p加上1,这里的括号其实可以省略,因为这是由于 p++ 的特性决定的(先使用再加1); *p->str读取的是指针str所指向的对象的值;
     
    *p->str++先读取指针str指向的对象的值,然后再将str加上1(与*s++相同):
    struct point {
        char * str;
        inty;
    }/* *p */;
    int main(int argc, char * argv[]) {
        //这里的结构指针变量不能在外层结构体声明时在后面定义,
        //否则运行时会出问题,不知道原因是什么,但书上好像也
        //是这么定义的
        struct point *p;
        p->str = "abcd";
        printf("%c ", *p->str++);//a
        printf("%s", p->str);//bcd
        return 0;
    }
     
    (*p->str)++将指针str指向的对象的值加1
    *p++->str先读取指针str指向的对象的值,然后再将p1
     
    结构数组:
    struct point {
        char * str;
        inty;
    } keytab[] = { { "auto", 0 }, { "break", 1 } };
    如果初值是简单变量或字符串,并且其中的任何值都不为空,则内层的花括号可以省略。通常情况下,如果初值存在并且方括号[]中没有数值,编译程序将计算数组keytab中的基数。
     
    结构指针:
    struct point {
        char * str;
        inty;
    };
    int main(int argc, char * argv[]) {
        struct point keytab1 = { "auto1", 1 };
        struct point keytab2[] = { { "auto2", 2 }, { "break", 1 } };
     
        struct point *p1 = &keytab1;//可以指向一个结构体变量
        printf("%s ", p1->str);//auto1
        printf("%c ", *p1->str);//a
        printf("%s ", p1->str + 1);//uto1 注,这里是先取地址,再将地址加1
       
        struct point *p2 = keytab2;//也可以指向一个结构体数组对象
        printf("%s ", (p2 + 1)->str);//break
     
        return 0;
    }

    sizeof


    C语言提供了一个编译进一元运算符sizeof,它可以用来计算任一对象的长度,表达式:
    sizeof 对象
    以及
    sizeof(类型名)
    将返回一个无符号整数,它等于指定对象或类型占用的存储空间字节数。其中对象可以是变量、数组或结构;类型可以是基本类型,如intdouble,也可以是派生类型,如果结构类型或指针类型。针对以下结构体:
    struct point {
        char * str;
        inty;
    } keytab[] = { { "auto", 0 }, { "break", 1 } };
    结构对象与结构类型长度计算如下:
        printf("%d ", sizeof keytab);//16
        //因为结构体中每个成员的长度是按最长成员来计算的,所以不是5,而是8
        printf("%d", sizeof (struct point));//8
     
    注,sizeof可以用在 #define 语句中,但不能用在条件编译语句 #if 中。

    类型定义(typedef)


    typedef int Length;Length定义为与int具有同等意义的名字。类型Length可用于类型声明、类型转换等,它和类型int完全相同:
    Length len,maxlen;
    Length *lengths[];
    类似地,声明
    typedef char * String;
    String定义为与char*或字符指针同义,此后便可以在类型声明和类型转换中使用String,例如:
    String p;
    int strcmp(String,String);
    p=(String)malloc(100);
     
    也可定义结构体:
    typedef structtnode {
        char * str;
        inty;
    } Treenode;
    typedef struct tnode * Treeptr;
     
    定义函数指针:
    typedef int (*PFI)(char *,char *);
    该语名定义了类型PFI是“一个指向函数的指针,该函数具有两个char * 类型的参数,返回值类型为int”,定义后,可以这样使用:
    PFI strcmp,numcmp;

    联合体(union)


    一个联合体变量可以合法地保存多种数据类型中任何一种类型的对象(同一时刻只能保存某一种),读取的类型必须是最近一次存入的类型:

    可变参数


    可以使用<stdarg.h>中的一组宏定义来操纵可参数。
     
    VA_LIST的用法:     
    1)首先在函数里定义一具VA_LIST型的变量,这个变量是指向参数的指针
    2)然后用VA_START宏初始化变量刚定义的VA_LIST变量,这个宏的第二个参数是第一个可变参数的前一个参数,是一个固定的参数。
    3)然后用VA_ARG返回可变的参数,VA_ARG的第二个参数是你要返回的参数的类型。
    4)最后用VA_END宏结束可变参数的获取。然后你就可以在函数里使用第二个参数了。如果函数有多个可变参数的,依次调用VA_ARG获取各个参数。
     
    #include<stdio.h>
    #include<stdarg.h>
    /*求和*/
    int sum(int first, ...) {
        int sum = 0, i = first;
        va_list marker;//定义一具VA_LIST型的变量,这个变量是指向参数的指针
        /*first一般表示可变参数列表中的前面最近第一个有名参数,如果前面有多个有
         * 名参数,即使这里指定为前面最近第二个有名参数,但可变参数列表还是从最
         * 后一个有名参数后面算起,对无名可变参数列表没有影响,但编译时会出警告,
         * 另外,参数列表中至少要有一个命名参数,如果连一个命名参数也没有,就无法使用可变参数*/
        va_start( marker, first ); /* VA_START宏初始化变量刚定义的VA_LIST变量,
                                这个宏的第二个参数是第一个可变参数的前一个参数,
                                是一个固定的参数。*/
     
        while (i != -1) {
           sum += i;
           i = va_arg( marker, int);//VA_ARG返回可变的参数,VA_ARG的第二个参数是你要返回的参数的类型。
        }
        va_end( marker ); /* VA_END宏结束可变参数的获取     */
        return sum;
    }
     
    main(void) {
        /* Call with 3 integers (-1 is used as terminator). */
        printf("sum is: %d ", sum(2, 3, 4, -1));//9
        /* Call with 4 integers. */
        printf("sum is: %d ", sum(5, 7, 9, 11, -1));//32
        /* Call with just -1 terminator. */
        printf("sum is: %d ", sum(-1));//0
    }
     

    字符串操作函数


    在头文件<string.h>中定义。在下面的各个函数中,stchar*类型,cnint类型。
    strcat(s, t)                       t指向的字符串连接到s指向的字符串的末尾
    strncat(s, t, n)               t指向的字符串中前n个字符连接到s指向的字符申的末尾
    strcmp(s, t)                    根据s指向的字符串小于(s<t)、等于(s==t)或大于(s>t) t指向的字符串的不同情况,分别返回负整数、0、或正整数
    strncmp(s, t, n)            strcmp相同,但只在前n个字符中比较
    strcpy(s, t)                      t指向的字符串复制到s指向的位置
    strncpy (s, t, n)            t指向的字符串中前n个字符复制到s指向的位置
    strlen(s)                          返回s指向的字符串的长度
    strchr(s, c)                      s指向的字符串中查找c,若找到,则返回指向它第一次出现的位置的指针,否则返回NULL
    strrchr(s, c)                             s指向的字符串中查找c,若找到,则返回指向它最后一次出现的位置的指针,否则返回NULL

    字符测试和转换函数


    头文件<ctype.h>中定义了一些用于字符侧试和转换的函数.在下面各个函数中,c是一个可表示为unsigned char类型或EOFint对象。该函数的返回值类型为int
    isalpha(c)                                 c是字母,则返回一个非0值,否则返回0
    isupper(c)                               c是大写字母,则返回一个非0值,否则返回0
    islower(c)                                c是小写字母,则返回一个非0值,否则返回0
    isdigit(c)                                   c是数字,则返回一个非0值,否则返回0
    isalnum(c)                             isalpha(c)isdigit(c),则返回一个非0值,否则返回0
    isspace(c)                                         c是空格、横向制表符( )、换行符( )、回车符( ),换页(f)符或纵向制表符(v),则返回一个非0值,否则返回0
    toupper(c)                                       返回c的大写形式
    tolower(c)                              返回c的小写形式

    数学函数


    头文件<math.h>中声明了20多个数学函数。下面介绍一些常用的数学函数,每个函数带有一个或两个double类型的参数,并返回一个double类型的值。
    exp (x)                                         指数函数ex
    log (x)                                          x的自然对数(以e为底),其中,x>0
    1og10(x)                                  x的常用对数(以10为底),其中,x>0
    pow(x, y)                                             计算xy的值
    sqrt(x)                                         x的平方根(x>=0
    fabs(x)                                                x的绝对值

    随机函数


        函数rand()生成介于0RAND_MAX之间的伪随机整数序列。其中RAND_MAX是在头文件<stdlib.h>中定的符号常量。下面是一种生成大于等于0但小于1的随机浮点数的方法
        #define frand() ((double) rand() / (RAND_MAX+1.0))
    (如果所用的函数库中已经提供了一个生成浮点随机数的函数,那么它可能比上面这个函数具有更好的统计学特性)
        函数srand(unsigned)设置rand函数的种子数。

    存储管理函数(malloc/ calloc)


    函数malloccalloc用于动态地分配存储块。函数malloc的声明如下:
        void *malloc(size_t n)
    当分配成功时,它返回一个指针,设指针指向n字节长度未初始化的存储空间,否则返回NULL。函数calloc的声明为
       void *calloc(size_t n, size_t size)
    当分配成功时,它返回一个指针,该指针指向的空闲空间足以容纳由n个指定长度的对象组成的数组,否则返回NULL该存储空间被初始化为0
     
        根据请求的对象类型,ma11occalloc函数返回的指针满足正确的对齐要求。下面的例子进行了类型转换:
        int *ip;
    ip=(int *) calloc(n, sizeof(int))
     
        free(p)函数释放p指向的存储空间,其中,p是此前通过调用malloccalloc函数得到的指针。存储空间的释放顺序没有什么限制,但是,如果释放一个不是通过调用malloccallloc函数得到的指针所指向的存储空间,将是一个很严重的错误
        使用己经释放的存储空间同样是错误的。下面所示的代码是一个很典型的错误代码段,它通过一个循环释放列表中的节点:
        for (p=head; p !=NULL; p=p->next)
            free(p);
    正确的处理方法是,在释放节点之前先将一切必要的信息保存起来,如下所示
      for (p=head; p!=NULL; p=9)
            q= p->next;
            free(p);
      }
     
     
  • 相关阅读:
    在你设计中可能用到的20个杂志 PSD 原型
    Gradify
    CamanJS – 提供各种图片处理的 JavaScript 库
    免费素材:包含 250+ 组件的 DO UI Kit
    24个很赞的 Node.js 免费教程和在线指南
    Dynamics.js
    Page Scroll Effects
    Slides
    15款加速 Web 开发的 JavaScript 框架
    Wee – 为现代 Web 开发打造的 CSS 脚手架
  • 原文地址:https://www.cnblogs.com/jiangzhengjun/p/4256069.html
Copyright © 2011-2022 走看看