版主开设这一个坑的目的也是为了加深自身对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[];却有着千差万别,这个作为后话