C/C++ 学习笔记

在用C/C++进行开发的时候,记录一下碰到过的问题,希望能够帮助别人

 

1.Typeof

  typeof是GCC的一个扩展,在linux下可以使用,很多文章说是关键字,这个算是误导吧,起码不是C标准的东西。详情参见

  在MingW下,可用decltype代替,这个问题在使用uthash的类库时发现的,在预定义宏里,有TYPEOF的定义,使用过的同学可以看看 : )

   (以下代码在VS2010编译通过)

#if defined __cplusplus
#define TYPEOF(x) (typeof(x))
#else
#define TYPEOF(x)
#endif

  改为

#if defined __cplusplus
#define TYPEOF(x) (decltype(x))
#else
#define TYPEOF(x)
#endif

 

 2.指针

  因为需要,在C中进行自定义事件系统,就像JAVA或者javascript的一样,当你需要监听一个事件的时候,通常是将处理函数与事件相绑定,那在C/C++中,大家想到的肯定是传递函数指针来进行事件绑定啦,我也是这样做的。

  定义事件监听函数,根据事件名,对事件进行监听

BOOL addEventListener(char* eventName,int (*fun)(EventObject* e));

  其中:

int (*fun)(EventObject* e)

  fun定义的函数指针,int指定了fun指向的函数的返回类型,而EventObject* e 指定了该函数的参数列表。可以这样理解 fun指向了如下格式的函数

int eventListener(EventObject* e){
}

  这样就可以通过函数指针添加事件监听了,不过使用C++的同学要注意了,这里的函数指针,指向的是全局函数,即非对象成员函数。C/C++在定义指针类型的时候,分别定义了4种类型的指针,分别是:变量指针,函数指针,成员变量指针,成员函数指针。不同类型的指针,不能够随意转化。所以说如果使用函数指针来传递一个成员函数的话,编译是会报错的。这里可以采用网上提供的开源类库,不过我并没有深究,有兴趣的同学可以研究一下,欢迎探讨 ^_^!


3.局部变量想要被当作全局变量来使用

  这是我犯得一个错误,在此提醒跟我同样错误的同学,要小心了,先上代码

 

#include <stdio.h>
struct linkList{
linkList * prev;
int number;
linkList * next;
} ;

linkList * newElement(){
linkList * temp = new linkList;
return temp;
}

linkList * newElement2(){//这个写法是错误的
linkList temp;
return &temp;
}

void linkListMain(){
linkList * cur = 0;
linkList * newLinkList;

linkList head;
head.prev = 0;
head.number = 0;
head.next = 0;

cur = &head;
for(int i = 1 ; i <= 10 ; i++){
//定义新节点

newLinkList = newElement();

newLinkList->prev = cur;//新节点的前一个是当前临时指针
newLinkList->number = i;//设置number
newLinkList->next = 0;//下一个为空

cur->next = newLinkList;//设置临时指针的下一个是当前节点
cur = newLinkList;//临时指针指向当前节点

}



cur = &head;

for(int i = 0 ; i < 10 ; i++ ){
printf("current dataNumber is %d \n",cur->number);
cur = cur->next;
}



getchar();
}


  这里定义了两种获取链表元素的方法,分别是newElement和newElement2,执行结果应该是将链表内保存的数字从头显示到尾,应该是0~9,newElement是对的,newElement2的输出结果全是10,那么这是为什么呢?这里就要说到程序的调用堆栈了。

  一个函数,在其中定义的变量,都会在其调用栈中进行分配内存,那么当这个函数调用完毕后,调用栈弹栈,这其中的变量就会失效。但是如果你在循环内部反复执行一个方法,并且如用其中的局部变量作为返回值,有时你会发现,居然可以当作全局变量使用,并不是调用结束就被销毁,这是为什么呢?这是因为循环执行速度过快,导致内存尚未被释放而又被再次使用(这是我推测的,大家可以验证一下),而且函数内部变量的内存地址,相对函数的内存地址,位移是在程序启动的时候就确定了。假设方法fun1()的内存地址是0x0001 0000,那么其中的变量内存地址应该是0x0001 0010,他们的差值在本次运行过程中,始终是0x10,在你重复快速的访问状态下,或始终更新这个内存地址内的值,也就导致了newElement2的输出结果最终都是9,因为链表中所有的内容指针,都全部指向了函数中的同一个地址,这个地址内容在循环完成后,变成了10,所以显示结果全部是10.

  而newElement采用new的方式分配内存,就把这个变量内存地址创建在了堆中,这并不会因为函数执行完毕,调用栈弹栈导致变量注销而产生问题。

  这两个方法还有一个本质的区别就是返回值的不同,采用new方法分配内存,每次都是新的内存,而在函数内利用声明直接定义变量,则会产生“静态”的效果。

 

 

以上内容,都是本人自己的理解,并不保证完全正确,如果大家发现有什么不对的地方,欢迎指出。

即时更新

posted @ 2012-01-05 14:49  Tony_J  阅读(456)  评论(1编辑  收藏  举报