• C puzzles详解【46-50题】


    第四十六题

    What does the following macro do? 
      #define ROUNDUP(x,n) ((x+n-1)&(~(n-1)))
    题目讲解:
    参考:http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=814501
    用于内存对齐,n为2的幂。

    第四十七题

    Most of the C programming books, give the following example for the definition of macros. 
      #define isupper(c) (((c) >= 'A') && ((c) <= 'Z'))
    But there would be a serious problem with the above definition of macro, if it is used as follows (what is the problem??) 
      char c;
      /* ... */
      if(isupper(c++))
      {
          /* ... */
      }
    But most of the libraries implement the isupper (declared in ctypes.h) as a macro (without any side effects). Find out how isupper() is implemented on your system.
    知识点讲解:
    Linux内核中isupper的实现见lib/ctype.c和include/linux/ctype.h。
    ctype.h代码如下:
    #ifndef _LINUX_CTYPE_H
    #define _LINUX_CTYPE_H
    
    /*
     * NOTE! This ctype does not handle EOF like the standard C
     * library is required to.
     */
    
    #define _U    0x01    /* upper */
    #define _L    0x02    /* lower */
    #define _D    0x04    /* digit */
    #define _C    0x08    /* cntrl */
    #define _P    0x10    /* punct */
    #define _S    0x20    /* white space (space/lf/tab) */
    #define _X    0x40    /* hex digit */
    #define _SP    0x80    /* hard space (0x20) */
    
    extern const unsigned char _ctype[];
    
    #define __ismask(x) (_ctype[(int)(unsigned char)(x)])
    
    #define isalnum(c)    ((__ismask(c)&(_U|_L|_D)) != 0)
    #define isalpha(c)    ((__ismask(c)&(_U|_L)) != 0)
    #define iscntrl(c)    ((__ismask(c)&(_C)) != 0)
    #define isdigit(c)    ((__ismask(c)&(_D)) != 0)
    #define isgraph(c)    ((__ismask(c)&(_P|_U|_L|_D)) != 0)
    #define islower(c)    ((__ismask(c)&(_L)) != 0)
    #define isprint(c)    ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
    #define ispunct(c)    ((__ismask(c)&(_P)) != 0)
    /* Note: isspace() must return false for %NUL-terminator */
    #define isspace(c)    ((__ismask(c)&(_S)) != 0)
    #define isupper(c)    ((__ismask(c)&(_U)) != 0)
    #define isxdigit(c)    ((__ismask(c)&(_D|_X)) != 0)
    
    #define isascii(c) (((unsigned char)(c))<=0x7f)
    #define toascii(c) (((unsigned char)(c))&0x7f)
    
    static inline unsigned char __tolower(unsigned char c)
    {
        if (isupper(c))
            c -= 'A'-'a';
        return c;
    }
    
    static inline unsigned char __toupper(unsigned char c)
    {
        if (islower(c))
            c -= 'a'-'A';
        return c;
    }
    
    #define tolower(c) __tolower(c)
    #define toupper(c) __toupper(c)
    
    #endif
    ctype.c代码如下:
    /*
     *  linux/lib/ctype.c
     *
     *  Copyright (C) 1991, 1992  Linus Torvalds
     */
    
    #include <linux/ctype.h>
    #include <linux/module.h>
    
    const unsigned char _ctype[] = {
    _C,_C,_C,_C,_C,_C,_C,_C,                /* 0-7 */
    _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C,            /* 8-15 */
    _C,_C,_C,_C,_C,_C,_C,_C,                /* 16-23 */
    _C,_C,_C,_C,_C,_C,_C,_C,                /* 24-31 */
    _S|_SP,_P,_P,_P,_P,_P,_P,_P,                /* 32-39 */
    _P,_P,_P,_P,_P,_P,_P,_P,                /* 40-47 */
    _D,_D,_D,_D,_D,_D,_D,_D,                /* 48-55 */
    _D,_D,_P,_P,_P,_P,_P,_P,                /* 56-63 */
    _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U,        /* 64-71 */
    _U,_U,_U,_U,_U,_U,_U,_U,                /* 72-79 */
    _U,_U,_U,_U,_U,_U,_U,_U,                /* 80-87 */
    _U,_U,_U,_P,_P,_P,_P,_P,                /* 88-95 */
    _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L,        /* 96-103 */
    _L,_L,_L,_L,_L,_L,_L,_L,                /* 104-111 */
    _L,_L,_L,_L,_L,_L,_L,_L,                /* 112-119 */
    _L,_L,_L,_P,_P,_P,_P,_C,                /* 120-127 */
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,            /* 128-143 */
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,            /* 144-159 */
    _S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,    /* 160-175 */
    _P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,    /* 176-191 */
    _U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,    /* 192-207 */
    _U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L,    /* 208-223 */
    _L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,    /* 224-239 */
    _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L};    /* 240-255 */
    
    EXPORT_SYMBOL(_ctype);
    _ctype数组中的每个元素的值对应ASCII码为0-255的每个字符的类型,以字符的ASCII码为索引即可获取到相应字符的类型。

    第四十八题

    I hope you know that ellipsis (...) is used to specify variable number of arguments to a function. (What is the function prototype declaration for printf?) What is wrong with the following delcaration? 
      int VarArguments(...)
      {
          /*....*/
          return 0;
      }
    知识点讲解:
    对于带有不定参数的函数,用va_start,va_arg,va_end对参数进行索引,内核代码中va_*系列函数的实现在
    include/acpi/platform/acenv.h中

    #ifndef va_arg
    
    #ifndef _VALIST
    #define _VALIST
    typedef char *va_list;
    #endif                /* _VALIST */
    
    /*
     * Storage alignment properties
     */
    #define  _AUPBND                (sizeof (acpi_native_int) - 1)
    #define  _ADNBND                (sizeof (acpi_native_int) - 1)
    
    /*
     * Variable argument list macro definitions
     */
    #define _bnd(X, bnd)            (((sizeof (X)) + (bnd)) & (~(bnd)))
    #define va_arg(ap, T)           (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND))))
    #define va_end(ap)              (void) 0
    #define va_start(ap, A)         (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))
    
    #endif                /* va_arg */
    由如上定义可知,va_start返回第一个不定参数的地址,va_arg返回下一个不定参数的地址,va_end用来销毁ap。
    va_start和va_end总是成对使用。
    va_start获取第一个不定参数的地址时,必须知道最后一个固定参数A的地址,即函数必须提供至少一个固定参数。
    故定义形如VarArguments(...)的函数是不正确的。

    第四十九题

    Write a C program to find the smallest of three integers, without using any of the comparision operators.
    题目讲解:
    参考:
    http://www.geeksforgeeks.org/smallest-of-three-integers-without-comparison-operators/
    方法一:
    int smallest(int x, int y, int z)
    {
      int c = 0;
      while ( x && y && z )
      {
          x--;  y--; z--; c++;
      }
      return c;
    }
    方法二:
    #define CHAR_BIT 8
    
    /*Function to find minimum of x and y*/
    int min(int x, int y)
    {
      return  y + ((x - y) & ((x - y) >>
                (sizeof(int) * CHAR_BIT - 1)));
    }
    
    /* Function to find minimum of 3 numbers x, y and z*/
    int smallest(int x, int y, int z)
    {
        return min(x, min(y, z));
    }
    方法三:
    // Using division operator to find minimum of three numbers
    int smallest(int x, int y, int z)
    {
        if (!(y/x))  // Same as "if (y < x)"
            return (!(y/z))? y : z;
        return (!(x/z))? x : z;
    }

     

    第五十题

    What does the format specifier %n of printf function do?
    参考:
    http://www.geeksforgeeks.org/g-fact-31/
    如:
    printf("geeks for %ngeeks ", &c);
    将%n之前的字符数赋值给c。
  • 相关阅读:
    树的子结构(剑指offer_26)
    合并两个排序的链表(剑指offer_25)
    反转链表(剑指offer_24)多看多思多想
    链表中环的入口结点(剑指offer_23)
    链表中倒数第k个节点
    调整数组顺序使奇数位于偶数前面(剑指offer_21)
    表示数值的字符串(剑指offer_20)
    1676. 跳石头
    1670. 回合制游戏
    1667. 区间统计(回顾)
  • 原文地址:https://www.cnblogs.com/tanghuimin0713/p/3989423.html
Copyright © 2020-2023  润新知