第二章习题
2.1 在2.8节中基本数据类型可以在多个文件中定义。例如,在FreeBSD 8.0中,size_t在29个不同的文件中都有定义,由于一个程序可能包含这29个不同的头文件,在ISO C 却不允许对同一个名字进行多次typedef,那么如何编写这些头文件呢?
为了避免多次包含typedef语句,我们可以使用#ifndef标识
#ifndef _MACHINE_TYPES_H_
#define _MACHINE_TYPES_H_
typedef int _int32_t;
typedef unsigned int _uint32_t;
.........
typedef _uint32_t _size_t;
.........
#enddef
2.2 检查系统的头文件,列出基本系统数据所用到的实际数据类型
1、我所使用的为Linux系统,发行版为Fedora,基本数据类型所在头文件为
/usr/include/sys/types.h中
#include
#ifdef __USE_MISC
# ifndef __u_char_defined
typedef __u_char u_char;
typedef __u_short u_short;
typedef __u_int u_int;
typedef __u_long u_long;
typedef __quad_t quad_t;
typedef __u_quad_t u_quad_t;
typedef __fsid_t fsid_t;
# define __u_char_defined
# endif
#endif
这里找到的仍然不是题目所要求的实际数据类型,我们便从
#include 中查找
#include
#include
/* Convenience types. */
typedef unsigned char __u_char;
typedef unsigned short int __u_short;
typedef unsigned int __u_int;
typedef unsigned long int __u_long;
/* Fixed-size types, underlying types depend on word size and compiler. */
typedef signed char __int8_t;
typedef unsigned char __uint8_t;
typedef signed short int __int16_t;
typedef unsigned short int __uint16_t;
typedef signed int __int32_t;
typedef unsigned int __uint32_t;
#if __WORDSIZE == 64
typedef signed long int __int64_t;
typedef unsigned long int __uint64_t;
#else
__extension__ typedef signed long long int __int64_t;
__extension__ typedef unsigned long long int __uint64_t;
#endif
/* quad_t is also 64 bits. */
#if __WORDSIZE == 64
typedef long int __quad_t;
typedef unsigned long int __u_quad_t;
#else
__extension__ typedef long long int __quad_t;
__extension__ typedef unsigned long long int __u_quad_t;
#endif
2.3 改写图2-17中的程序,使其在sysconf为OPEN_MAX限制返回LONG_MAX时,避免进行不必要的处理。
1、源程序:
/*************************************************************************
> File Name: openmax.c
> Author: King
> Mail: arturiapendragon_1@163.com
> Created Time: 2017年05月03日 星期三 19时05分42秒
************************************************************************/
#include "apue.h"
#include
#include
#ifdef OPEN_MAX
static long openmax = OPEN_MAX;
#else
static long openmax = 0;
#endif
/*
* If OPEN_MAX is indeterminate, this might be inadequate
*/
#define OPEN_MAX_GUESS 256
long open_max(void)
{
if (openmax ==0){ /* first time through */
errno = 0;
if ((openmax = sysconf(_SC_OPEN_MAX)) < 0) {
if (errno == 0)
openmax = OPEN_MAX_GUESS; /* it's indeterminate */
else
err_sys("sysconf error for _SC_OEPN_MAX");
}
}
return(openmax);
}
int main(void)
{
printf("%ld\n",open_max());
}
执行结果为:
king at Fedora in ~/apue/chapter2
$ gcc openmax.c
king at Fedora in ~/apue/chapter2
$ ./a.out
1024
因为sysconf函数在Linux可能返回的是LONG,造成程序执行混乱:
因此,修改后的程序:
/*************************************************************************
> File Name: openmax.c
> Author: King
> Mail: arturiapendragon_1@163.com
> Created Time: 2017年05月03日 星期三 19时05分42秒
************************************************************************/
#include "apue.h"
#include
#include
#include //为了支持getrlimit函数以及结构体rlimit的使用
#ifdef OPEN_MAX
static long openmax = OPEN_MAX;
#else
static long openmax = 0;
#endif
/*
* If OPEN_MAX is indeterminate, this might be inadequate
*/
#define OPEN_MAX_GUESS 256
long open_max(void)
{
struct rlimit rl;
if (openmax ==0){ /* first time through */
errno = 0;
if ((openmax = sysconf(_SC_OPEN_MAX)) < 0 || openmax==LONG_MAX) {
if((openmax=getrlimit(RLIMIT_NOFILE,&rl))<0){
err_sys("can not get file limit\n");
}else if(openmax==RLIM_INFINITY)
openmax = OPEN_MAX_GUESS;
else
openmax=rl.rlim_max;
}
}
return(openmax);
}
int main(void)
{
printf("%ld\n",open_max());
}
通过man getrlimit可查看getrlimit函数的实现以及参数:
The value RLIM_INFINITY denotes no limit on a resource (both in the structure returned by getrlimit() and in the structure passed to setrlimit()).
RLIMIT_NOFILE
Specifies a value one greater than the maximum file descriptor number that can be opened by this process. Attempts (open(2), pipe(2), dup(2),
etc.) to exceed this limit yield the error EMFILE. (Historically, this limit was named RLIMIT_OFILE on BSD.)