APUE编译问题

本文解决一些APUE一书中例子编译过程中的问题

OS: ubuntu 12.04

  • 问题

    /usr/include/bits/timex.h:31:7:error: expect ':' , ',' , ';' , '}' or '__attribute__'
    

    解决

    apue.2e/ipp/ipp.h中 #define status u.st 与 timex.h中的 status 冲突,更改 #define Status u.st

  • 问题

    ARG_MAX 未定义

    解决

    • 在include/apue.h中加入 #define ARG_MAX 4096
    • 在threadctl/getenv1.c 加入 #include “../include/apue.h”
    • 在threadctl/getenv3.c 加入 #include “../include/apue.h”

OS: mac os 10.7.4

问题

Undefined symbols for architecture x86_64:"_CMSG_LEN", referenced from:_recv_fd in libapue.a(recvfd.o)
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status

解决

在include/apue.h中增加

#if defined(SOLARIS)
#define _XOPEN_SOURCE   500 /* Single UNIX Specification, Version 2  for Solaris 9 */
#define CMSG_LEN(x) _CMSG_DATA_ALIGN(sizeof(struct cmsghdr)+(x))
#elif defined(MACOS)  /*新增行*/
#elif !defined(BSD)
#define _XOPEN_SOURCE   600 /* Single UNIX Specification, Version 3 */
#endif

递归模板实现单例模式

 #include <iostream>
    using namespace std;

    template<class T> class Singleton {
        Singleton(const Singleton&);
        Singleton &operator=(const Singleton&);
    protected:
        Singleton() {}
        virtual ~Singleton() {}
    public:
        static T &instance() {
            static T theInstance;
            return theInstance;
        }
    };

    // A sample class to be made into a Singleton
    class MyClass : public Singleton<MyClass> {
        int x;
    protected:
        friend class Singleton<MyClass>;
        MyClass() { x = 0; }
    public:
        void setValue(int n) { x = n; }
        int getValue() const { return x; }
    };

    int main() {
        MyClass &m = MyClass::instance();
        cout << m.getValue() << endl;
        m.setValue(1);
        cout << m.getValue() << endl;
    }

结构体中的冒号位域

有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位域来表示。一、位域的定义和位域变量的说明位域定义与结构定义相仿,其形式为:

域结构名

{ 位域列表 };

其中位域列表的形式为: 类型说明符 位域名:位域长度 例如:

struct bs 
{ 
    int a:8; 
    int b:2; 
    int c:6; 
};

位域变量的说明与结构变量说明的方式相同。 可采用先定义后说明,同时定义说明或者直接说明这三种方式。例如:

struct bs 
{ 
    int a:8; 
    int b:2; 
    int c:6; 
}data;

说明data为bs变量,共占两个字节。其中位域a占8位,位域b占2位,位域c占6位。对于位域的定义尚有以下几点说明: \1. 一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。例如:

struct bs 
{ 
    unsigned a:4 
    unsigned :0 /*空域*/ 
    unsigned b:4 /*从下一单元开始存放*/ 
    unsigned c:4 
}

这个位域定义中,a占第一字节的4位,后4位填0表示不使用,b从第二字节开始,占用4位,c占用4位。 \2. 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如:

struct k 
{ 
    int a:1 
    int :2 /*该2位不能使用*/ 
    int b:3 
    int c:2 
};

从以上分析可以看出,位域在本质上就是一种结构类型, 不过其成员是按二进位分配的。 简而言之,言而简之 这是位域操作的表示方法,也就是说后面加上“:1”的意思是这个成员的大小占所定义类型的1 bit,“:2”占2 bit,依次类推。当然大小不能超过所定义类型包含的总bit数。 一个bytes(字节)是8 bit(bit)。例如你的结构中定义的类型是u_char,一个字节,共8bit,最大就不能超过8。 32位机下, short是2字节,共16bit,最大就不能超过16. int是4字节,共32bit,最大就不能超过32. 依次类推。 这样定义比较省空间。例如你上面的结构,定义的变量类型是u_char,是一字节类型,即8bit。 fc_subtype占了4bit,fc_type占2bit,fc_protocol_version占2bit,共8bit,正好是一个字节。 其他八个成员,各占1bit,共8bit,正好也是一个字节。 因此你的结构的大小如果用sizeof(struct frame_control)计算,就是2bytes.

埃拉托斯特尼筛选法

埃拉托斯特尼筛选法又称筛法,是求不超过自然数N(N>1)的所有质数的一种方法。据说是古希腊的埃拉托斯特尼(Eratosthenes,约公元前274~194年)发明的,又称埃拉托斯特尼筛子。 具体做法是: 先把N个自然数按次序排列起来。1不是质数,也不是合数,要划去。第二个数2是质数留下来,而把2后面所有能被2整除的数都划去。2后面第一个没划去的数是3,把3留下,再把3后面所有能被3整除的数都划去。3后面第一个没划去的数是5,把5留下,再把5后面所有能被5整除的数都划去。这样一直做下去,就会把不超过N的全部合数都筛掉,留下的就是不超过N的全部质数。因为希腊人是把数写在涂腊的板上,每要划去一个数,就在上面记以小点,寻求质数的工作完毕后,这许多小点就像一个筛子,所以就把埃拉托斯特尼的方法叫做“埃拉托斯特尼筛”,简称“筛法”。(另一种解释是当时的数写在纸草上,每要划去一个数,就把这个数挖去,寻求质数的工作完毕后,这许多小洞就像一个筛子。)

    using std::size_t;
    using std::sqrt;
    using std::string;

    class SieveTest : public TestSuit::Test {
        string sieveChars;
    public:
        SieveTest() : sieveChars(50, 'P') {}
        void run() {
            findPrimes();
            testPrimes();
        }   
        bool isPrime(int p) {
            if(p == 0 || p == 1) return false;
            int root = int(sqrt(double(p)));
            for(int i = 2; i <= root; i++)
                if(p % i == 0) return false;
            return true;
        }   
        void findPrimes() {
            sieveChars.replace(0, 2, "NN");
            size_t sieveSize = sieveChars.size();
            int root = int(sqrt((double)(sieveSize)));
            for(int i = 2; i <= root; i++)
                for(size_t factor = 2; factor * i < sieveSize; ++factor)
}
        void testPrimes() {
            size_t i = sieveChars.find('P');
            while(i != string::npos) {
                test_(isPrime(i++));
                i = sieveChars.find('P', i);
            }
            i = sieveChars.find_first_not_of('P');
            while(i != string::npos) {
                test_(!isPrime(i++));
                i = sieveChars.find_first_not_of('P', i);
            }
        }
    };

ref: http://zh.wikipedia.org/wiki/%E5%9F%83%E6%8B%89%E6%89%98%E6%96%AF%E7%89%B9%E5

xlib创建一个OpenGL简单窗口

void CreateWindow(int width, int height) {
	XInitThreads();
	m_scrWidth = width;
	m_scrHeight = height;
	int attr[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_DOUBLEBUFFER, True,
			GLX_DEPTH_SIZE, 16, None, };
	m_dpy = XOpenDisplay(NULL);
	if (m_dpy == NULL) {
		cerr << "XOpenDisplay error" << endl;
		return;
	}
	int nelements;
	GLXFBConfig *fc = glXChooseFBConfig(m_dpy, 0, attr, &nelements);
	if (fc == NULL) {
		cerr << "glXChooseFBConfig error" << endl;
		return;
	}
	XVisualInfo *vi = glXGetVisualFromFBConfig(m_dpy, *fc);
	if (vi == NULL) {
		cerr << "glXGetVisualFromFBConfig error" << endl;
		return;
	}
	Colormap cmap = XCreateColormap(m_dpy, DefaultRootWindow(m_dpy), vi->visual,
			AllocNone);
	XSetWindowAttributes swa;
	swa.colormap = cmap;
	swa.event_mask = ExposureMask | KeyPressMask;
	m_win = XCreateWindow(m_dpy, DefaultRootWindow(m_dpy), 0, 0, m_scrWidth,
			m_scrHeight, 0, vi->depth, InputOutput, vi->visual,
			CWColormap | CWEventMask, &swa);
	XFree(vi);
	/* 显示窗口 */
	XMapWindow(m_dpy, m_win);
	/* 设置窗口的OpenGl属性 */
	m_glc = glXCreateNewContext(m_dpy, *fc, GLX_RGBA_TYPE, NULL, GL_TRUE);
	/* 绑定当前窗口到OpenGl */
	glXMakeContextCurrent(m_dpy, m_win, m_win, m_glc);
	/* 初始化OpenGl */
	initializeGl();
	glXSwapBuffers(m_dpy, m_win);
}