首页 > 代码库 > C puzzles详解【46-50题】
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 _VALISTtypedef 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 numbersint 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。
C puzzles详解【46-50题】
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。