专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »C语言教程 » 学习经验交流会:c语言学习经验交流 »正文

学习经验交流会:c语言学习经验交流

来源: 发布时间:星期四, 2008年9月25日 浏览:19次 评论:0

1.#include\"stdio.h\"
#include<stdio.h>
上次在网络教室上看到有人问这个问题 \"\"link的时候首先在相对路径下找.h,找不到然后在到path里面找,而<>直接在path里面找,path的设置可以查看环境变量一般window在安装目录的system32中,linux在user/lib里面

2 宏使用问题

宏替换一般在编译前,所以没有分配任何的空间,没有任何的类型可言,同时他是直接替换宏标号,所以使用一定要小心,有些人过分的喜欢用宏,其实宏的使用也不是越多越好,要防止代码的膨胀,现在的操作系统基本都是页式管理,当宏替换内容过大发生换页时,宏的效率不会比调用函数快,还好 c++ inline解决了这个问题

3 void f();
void f(void);
void f(...);
第一个函数的参数列表不是为空(c++里面是空),他的参数是不确定,第二个函数参数才为空,第三个函数是可变参数函数,很多库函数都是这样实现的如:典型的printf(...);

4.c语言里面只有值传递,(c++还有传引用),实际参数传进函数的时候,都会生成一些临时变量保存这些值,传指针也是同样的道理,故你可以改变指针指的内容,不可以改变指针本身,等于传的是 type * ptr const ;

5.副作用和序列号

整个程序在运行时总是处于某个状态,副作用能够引起这个状态的改变,而序列点是某个副作用已经改变而另一个没有开始的地方,俩个相临的序列点对一个左值只能够改变一次,可以多次使用.凡是有序列点问题的量最终的值都是不确定的 象x = ((++x) + (++x) + (++x)) ; f(x , x ++ ) 都存在这样的问题,具体的值看编译器是怎么理解,所以谈这样的问题是没有任何的意义


6数组越界问题
c语言为了追求最大的灵活和效率,不对数组进行边界检查,这些工作都是程序员自己的事情,不要以为你一越界编译器就会告诉你,只有当越界到编译器需要换页的时候才会报错,在理想情况下,window下可以越界64K,不过很不幸,我试过很多次,最多达到了30k,不过这个数字也是很恐怖的,30k的汇编代码足以对你的操作系统做任何事情.

7 int a[100] = {0};能否对数组初试化为零?初始化问题
这个是能够初始化为0的,因为在为数组初始化的时候,当初始化长度小于数组的大小的时候用0来补充,但是不提倡这样初始化,一般初试化可以用for循环或者memset()(string.h)函数来初始化,还有一种对static变量的初始化问题也是很有趣味的,static变量一般在静态数据区分配空间,对于局部的static变量采用的一种类似lazy initlazition的方法,在第一次使用的时候对其初始化,且初始化一次。在声明变量的时候对它进行初始化是个很好的习惯。经常遇到的问题是:
int i ;然后后面出来个 i ++ ; a [i++]......出了问题连自己也不知道。尤其对于指针 int *p = NULL ;是个很好的习惯,加上aasert()可以防止对空指针的访问。
在c++中初始化问题更加复杂。


8 malloc free
为什么很多人不喜欢c,c++,因为管理内存的一部分任何必须由程序员自己管理,不然很容易内存泄露,现在有很多检查内存泄露的软件比较常用的有(boundchecker)有兴趣的可以下个试一下自己的程序,你会发现自己好可怕。malloc free使用一般有几个原则(自己总结的,不一定正确,但很实用)[Page]
1 ,malloc free必须配套使用,并且尽可能逆序。
2 ,谁malloc的谁free
3,能够不动态分配的尽量不动态分配,动态分配是很费时间的,而且存在一定的风险。

很多人喜欢这样写程序:
type * f()
{
type *t = (type*)malloc ( sizeof(type));
.
.
return t ;
}
这个肯定会出问题,一般象这种情况,一般声明f(type* t),谁调用它谁为t分配空间,谁来释放它的空间。不过很有意思的是,在有写系统函数的会这样.如(char* asctime() ,它返回一个表示时间的字符指针,但是并不要求你释放,你也没有办法释放,但是我可以肯定它这个串肯定不是在堆区分配的)

free的顺序也很重要,很多时候free的时候会出现空指针的引用,不足为齐。有人提议free(t);t = NULL ;这种用法,有一定的道理,当你free一块空间后,操作系统不会立即回收,所以在你再次用t的时候可能还是可以用的,t就成了个野指针,而将其t = NULL后,对t的引用会出问题。


9对齐与字段问题
看下面俩个结构的定义

struct A (

char a ;
int b ;
} ;

struct B
{
char a:3;
int b:3 ;
}

对于A,sizeof(A) = 8的,因为存在一个对齐问题,按照电子计算机组成原理上面的说法,为了取数方便,对于半字型最后一位需是0,字型00,双字型000。A的长度需要是他里面数据长度最长那个的整数倍.

B是个字段问题,其实它很简单如 B:b表示的范围就是[-8,7],和其他的类型没有什么区别。

还介绍一个比较有技巧性的结构中的一个变量相对于结构的偏移量。比如求A中b相对于A的偏移量 &((A*)(0)->b) ;


10 数组和指针

首先请你记住,数组是数组,指针是指针,他们不是一回事。

int a[100];
int *p ;

a不是个左值,他不能够被改变,而p是可以的

看看sizeof(a) = 100 和sizeof(p) = 4(vc6.0)

对于字符串还要看看sizeof和strlen的区别:
sizeof还是数组的大小,strlen以0结束(不包括0)大家一定要注意因为不注意出现问题你都不知道怎么回事
如:

void f( char * p )
{
if ( p == NULL )
{
return ;
}
char *t ;
int lenOfP = strlen(p);
t = ( char *) malloc( sizeof(char) * lenOfP );
strcpy ( t , p ) ;
.
.
}

问题在那里,大家想想。这里有个越界。

数组和指针的差别远不止这些,你在运用中就会体会得到。下面有个很有意思的公式:
a[i] = *( a + i ) = * ( i + a ) = i[a] ;
呵呵 ,想想 char a[4] = \"abc\" ; 2[a] = \'t\' ; a[2] = ? ;

标签:

相关文章

读者评论

  • 共0条 分0页

发表评论

  • 昵称:
  • 内容: