C的陷阱与缺陷 P1-P42 PartI- 学习小结

版主开设这一个坑的目的也是为了加深自身对c的应用与理解,顺便见一见没用过的库函数。

1.= is not ==

Most languages originated from Algol(i.e.Pascal and Ada) use token ' := ' to embody  assignment and token '==' to embody if those two part aside the "==" are equal or not.

Let‘s see those codes below:

while(c=''||c=='\t'||c=='\n')
         c=getc(f);

This .c file may run for long cause the first line assigns c to be ' ' (space) which refers to 32 in ASCII standard.

Operator Precedence:

    同一优先级的运算符,运算次序由结合方向所决定。
    简单记就是:! > 算术运算符 > 关系运算符 > && > || > 赋值运算符

2.& and | is not && and || meanwhile '' is not ""

The first two are bit operator,while the last two are logical opearator.

现在基本上所有编辑器都能检测到’‘与“”的不同,van题不大。

3.词法的“贪婪” 

从左到右依次读入token,如果一个字符可能组成一个符号,那么在读入一个符号,看他们俩能不能组成一个符号,只要中间不嵌入无意义符号(space,\t,\n)就继续下去。比如==是一个符号,而= =是两个符号

再如,a---b is the same as a-- -b。

又如,y=a/*p,并不是a除以p指向的地址内容的值而是直接开始注释了。

And we can see what do "a+++b" and "a+++++b "mean。

1.再谈优先级:

假设有两个二进制信号一个叫flag一个叫FLAG,你需要判断他们是否是同一个信号,对他们合取&,当然你可以这么些if(flag&FLAG)意思是显然的;然而如果你需要显式表达的话,你可能会写出if(flag&FLAG != 0)然而!=的优先级却高于&,所以这串代码还是有问题的。

2.switch的break or no break

3.if-else的就近原则,加括号的重要性

举例:

if(x==0)
      if(y==0) error();
else
{
z=x+y;
f(&z);
}

4.我们再来复习一下数组与指针的相关内容:

int calendar[12][31];

int *p;

int i;

而calendar[4]是calendar数组的第五个元素,比如sizeof(calendar[4])=31*sizeof(int);

p=calendar[4];这个语句让p指向数组calendar[4]中下标为0的元素;同理,calendar[0]这个语句就是指向calendar[0]数组中下标为0的元素。

i=calendar[4][7]这个意思就是把calendar的第五个数组,数组中的第8个元素取出来赋值给i。

这个句子也可以写成i=*(calendar[4]+7);i=*(*(calendar+4)+7)

而p=calendar这个语句就是非法的,因为calendar是二维数组,而p是指向int的指针。

Obviously,我们需要一个能指向数组的指针。比如int (*ap)[31];

这句话的意思是声明*ap是一个拥有31个元素的整形数组,而ap就是一个指向这样的数组的指针。因而我们可以这么写:

int calendar[12][31];

int (*monthp)[31];

monthp=calendar..

假如在新年伊始之际,我们需要清空calendar数组,可以用如下两种形式(or more,anyway)来表示:

int month;
for(month=0;month<12;month++)
{
    int day;
    for(day=0;day<31;day++)
            calendar[month][day]=0;//or *(*(calendar+month)+day)=0;
}

//method 2 in ptr way

int (*monthp)[31];
for(monthp=calendar;monthp<&calendar[12];monthp++)
{
     int *dayp;
     for(dayp=*monthp;dayp<&(*monthp)[31];dayp++)
        *dayp=0
}

 

非数组的指针:假如我们有两个字符串s,t,希望把他们合成一个字符串r,该怎么办?

我们可以借助库函数strcpy and strcat,思路好想,但是可能写起来会有问题:

//错误演示
char *r;   //设置一个字符数组
strcpy(r,s);   //想把s复制给r
strcat(r,t);    //然后r后缀一个t

/*想法很好,但是是有问题的,原因是r指向何处是不确定的,我们可以看到,
不仅r得指向一个地址,并且r所指向的空间还得有足够的内存空间来容纳字符串,
根据C的特性,所以需要给r分配一定的空间,比如下面*/

char r[100];
strcpy(r,s);
strcat(r,t); //只要st的内存不要太大,这么写van题就不大,
如果我们不能获知st的相对规模的话,这怎么办呢

//malloc啊

char *r;
r=(char*)malloc(strlen(s),strlen(t));
strcpy(r,s);
strcat(r,t);

free(r);

作为参数的数组声明

在C语言中,我们没有办法直接把一个数组作为函数参数来传递,如果我们使用数组名作为参数,那么数组名竟会被立刻转换为只想该数组第一个元素的参数,比如啊 char hello[]="hello";

这声明了hello是一个数组,如果把这个数组作为函数参数传给一个函数,实际上和把数组的第一个元素的地址传给函数的作用完全等效,也就是说

printf("%s\n",hello);
和
printf("%s\n",&hello[0]);
是一样的

因此,将数组当成参数传给函数毫无意义,c会自动把作为参数的数组转换为相应的指针声明,也就是说下面俩也完全一样。

int strlength(cahr s[]){}
和
int strlength(char *s){}

但是extern char *hello[]和extern char hello[];却有着千差万别,这个作为后话

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值