Posts Tagged ‘C’

November 28, 2009
1
2
3
4
5
6
7
8
9
10
11
12
13
void fun1(char * str) {}
void fun2(char ** str) {}
 
//~ int main(int argc, char ** argv)
int main(int argc, char * argv[])
{
	char str1[] = "Hello, Piggy!";
	char str2[][4] = "Hello, Piggy!";
	fun1(str1);
	fun2(str2);
	fun2(&str1);
	return 0;
}

  上面的snippet有错误吗?有几个?你能找出来并说出原因吗?4、5两行有区别吗?想一下,然后看gcc给出的错误信息,

Tags: .
November 14, 2009

  看Chris对内联的总结,说到内联函数在编译时会被放入”符号表”,想一探究竟,结果却发现另外一个问题,疑惑不解。

1
2
3
4
5
6
7
#include <stdio.h>
inline int add(int a, int b) { return a + b; }
int main()
{
	int n = add(1,2);
	return 0;
}
Tags: ,,.
November 3, 2009

  这里面猫腻儿还真不少。

  karmic到源里面没有以前到vim-full包了,取而代之到是vim包,但现在有很多问题,n”+yy和n”+p无法和系统”剪切板”里到内容关联了,不知道什么原因。

Update
  一切都释然了,只要意识到,>也需要进行类型提升。那么后面到-1啦-2啦之类的,都是很大很大的数了,循环根本就进不去,更别提死循环了。这样看来四、五两段程序就没有必要列出来了。其实,我是被它们的汇编代码给迷惑住了。

Tags: ,,.
August 22, 2009
  1. 减少pthread_cond_signal和sem_post的调用,只在有必要的时候调用;
  2. 尽量避免pthread_mutex进入竞争态。增大消息队列的大小,可以有效减少竞态条件的出现。

/*
* 此处循环判断的原因如下:假设2个线程在getq阻塞,然后两者都被激活,
* 而其中一个线程运行比较块,快速消耗了2个数据,
* 另一个线程醒来的时候已经没有新数据可以消耗了。
* 另一点,man pthread_cond_wait可以看到,
* 该函数可以被信号中断返回,此时返回EINTR。
* 为避免以上任何一点,都必须醒来后再次判断睡眠条件。
* 更正:pthread_cond_wait是信号安全的系统调用,不会被信号中断。
*/

Tags: ,,.

表明看来似乎合情合理,由于C++的多态特性,允许我们将一个子类地址赋给父类型的指针pb,释放对象时理所当然的对pb进行delete。但,在程序运行时,并没有输出M destructed…,即D::m的析构函数没有被调用,而m的析构函数是需要D::~D()来调用的,所以子类D的析构函数也没有被调用。这是很容易理解的,因为父类的析构函数不是virtual的。由此,我们得出结论,用来继承的父类的析构函数总应该是virtual的,除非你确定它绝对不会被用于多态。关于这一点,《Effective C++》里面已经讲到了。

除了上面的问题,我们还应该关心的是,尽管析构函数没有被调用,那M::i的空间被释放了吗?It’s a question!由于析构函数没有被调用,那么释放M::i的任务就完全落在了delete身上的了,那么delete做到了吗?It’s a very question!这又回到了上一篇日志中所描述的问题上了。我的观点是delete做到了它应该做的事情,它只负责释放当初new申请的空间,即对象本身,至于对象里面是否有动态申请的内存,那就不是delete而是对象析构函数自己的工作了。

Tags: ,,.
August 19, 2009

源码之前,了无秘密。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//~ demo.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <streambuf>
using namespace std;
//~ 测试代码 :)
int main()
{
	ifstream in("demo.cpp");
	char buffer[4096]="original content in this buffer";
	cout<<buffer<<endl;
	streambuf * ptrbuff = in.rdbuf(); //~ 将streambuf与文件句柄关联
	ptrbuf->pubsetbuf(bufer, 4096); //~ 设置缓冲区,即设置in的缓冲区
	cout<<buffer<<endl; //~ 此时bufer里面的内容还是original content in this buffer
	string str;
	in>>str; //~ 真正要输入时bufer才被填充为in的内容
	cout<<str<<endl;
	cout<<buffer<<endl;
	return 0;
}

另外,还有一个filebuf,用法相近。看了很多C++方面的书,从来没有那本书对I/O流做过详细的介绍。C里面有setbuf可以修改缓冲区,但我在fstream里面却没看到这么个setbuf,rdbuf倒是有一个,它返回streambuf类型的指针。搜索streambuf的用法,无果,MSDN里面看到streambuf有一个setbuf的成员,甚喜。编译器说,setbuf是私有的,再看MSDN,还有一个pubsetbuf,哟西!

Tags: ,.
August 16, 2009
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
template <class T>
class Queue
{
public:
	Queue(int size = 30);
	~Queue();
	void EnQueue(T value);
	T DeQueue();
	T GetFirst();
	bool IsEmpty();
	bool IsFull();
	void ClearQueue();
private:
	T *queue;
	int front;
	int rare;
	int MaxSize;
	int CurLen;
};
Tags: ,,.

一个堆栈类模板,和用到此模板的一个表达式计算器。
输入四则运算表达式(可含括号),输出计算结果,暂未提供盛放运算和浮点数功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Stack   
{   
public:   
	Stack(int stack_size = 30);   
	~Stack();   
	void Push(T value);   
	T Pop();   
	T Top();   
	bool IsEmpty();   
	bool IsFull();   
	void ClearStack();   
private:   
	int top;   
	T* stack;   
	int size;   
};
Tags: ,,.
August 15, 2009

这里的内存会被正确释放吗?答案要分两方面来讨论。*pd对象本身的内存(4Byte)会不会被释放,就像上例中所说,我还是不知道。但(*pd)::pi所指向的内存肯定是打了水漂啦!因为delete看到的只是一个char*类型的pd,只会简单做一些处理(待高人讲解),而不会调用析构函数demo::~demo()。甚至有时候它会调用其他类的析构函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
using namespace std;
class demo
{
    public:
        //~ 此处省略代码数行……
        ~demo()
        {
             delete [] pi;
        }
    private:
        int * pi;
};
 
class foo
{
public:
    ~foo(){cout<<"foo's collapsing..."<<endl;
};
int
main()
{
    demo * pd = new demo;
    delete (foo*)pd;
    return 0;
}

foo童鞋真是可怜,让我们来了个借尸还魂,Orz,借刀杀人才对!

Tags: ,.
August 14, 2009
1
2
3
4
5
6
7
8
9
10
11
12
template <class T>
T Min(T x, T y)
{
	return x < y ? x : y;
}
 
int main()
{
	unsigned ui = 0;
	int a = Min(ui, 1);
	return 0;
}

这几行代码又有哪些错误呢?cl.exe提示说,error C2782: ‘T Min(T,T)’ : template parameter ‘T’ is ambiguous。在参数类型的确定上产生了不确定性,这是为什么呢?好吧,1会被解释成是int型的,但是我们平时不是经常把int直接传给unsigned类型的参数吗?可惜的是,此时的Min还不是一个函数,它只是一个模板而已,实例化之前尚不能完成参数的隐式转化(其实,我认为这只是编译器支持与否的问题)。同样,可以用显式特例化的方法来解决:
int a = Min(ui, 1); 或者 int a = Min(ui, 1);
当然,还可以强制类型转换:
int a = Min(ui, (unsigned)1); 或者 int a = Min(ui, 1);

Tags: ,.
Page 1 of 212Next