Skip to content

错题集

约 1315 个字 19 行代码 预计阅读时间 5 分钟

按照TonyCrane老师的分类整理一下,不知道来不来得及只有两个半小时了

一. 运算符优先级

优先级 运算符 结合律
1 后缀运算符:[] () · -> 从左到右
2 一元运算符:++ -- ! ~ +(正) -(负) * & sizeof 类型转换 从右到左
3 乘除法运算符:* / % 从左到右
4 加减法运算符:+ - 从左到右
5 移位运算符:<< >> 从左到右
6 关系运算符:< <= > >= 从左到右
7 相等运算符:== != 从左到右
8 位运算符 AND:& 从左到右
9 位运算符 XOR:^ 从左到右
10 位运算符 OR:| 从左到右
11 逻辑运算符 AND:&& 从左到右
12 逻辑运算符 OR:|| 从左到右
13 条件运算符:?: 从右到左
14 赋值运算符:= += -= *= /= %= &= ^= \|= <<= >>= 从右到左
15 逗号运算符:, 从左到右

二. 标识符关键词

  • define可以用作关键词,它只是预处理命令

三. 数据类型

  • 整型:
    • 十进制:123
    • 八进制:0123
    • 16进制:0x123
  • 字符型:
    • 八进制:\101,最多三个字符,8以上也不行
    • 16进制:x41,无长度限制

四. 指针相关

4.1. 多级指针

用递归来理解:

int var = 1;
int *p1=&var;
int **p=&p1;

(int **)p -> (int *)p1 -> (int) var

4.2. 区分指针数组和数组指针

  1. char *p[10]: 大小为10的数组,数据项是指针
  2. char (*p)[10]: *p是指针,指向大小为10的数组

4.3. 野指针问题

若指针声明未初始化,且未被赋值,则指向的内存无法确定,即野指针 不要尝试访问野指针即可

⚠注意定义的时候赋值和语句赋值的区别:比如下面这道题:

(C13A) In the following code fragments, item ___ is correct.

A. int *p; scanf("%d", &p);

B. int *p; scanf("%d", p);

C. int k, *p=&k; scanf("%d", p);

D. int k, *p; *p=&k; scanf("%d", p);

注意C和D的区别!C是定义了一个新的变量k,并且让p指向它,是合法的。 D中*p=&k是不合法的(相当于将k的地址写入p指向的空间,还是进行了访问)

假设 scanf 语句执行时输入 ABCDE<回车>,能使 puts(s) 语句正确输出 ABCDE 的程序段是 _____ A. char s[5] = {"ABCDE"}; puts(s); B. char s[5] = {'A', 'B', 'C', 'D', 'E'}; puts(s); C. char *s; scanf("%s", s); puts(s); D. char *s; s="ABCDE"; puts(s);

答案是D,剩下都涉及野指针的访问。D的操作:1)声明指针 2)让指针指向一个字符串 3)输出,完全正确

4.4. 隐式转换问题

4.4.1 函数指针

原理

任何函数指代器表达式,在用于异于下列语境

  • 作为取址运算符的操作数
  • 作为 sizeof 的操作数

会经历到指向表达式所指代函数的指针的转换。

function(20);
(function)(20);
(*&function)(20);
(&function)(20);
(*function)(20);
(***********function)(20); // 不用数了,11 个

No.4: C语言允许通过函数指针来调用函数 √ No.5: function作为取址运算符的操作数自动转化为function指针,即&function,这样再解引用,即function本身,√

4.5 指针杂项:

  1. int a[10]之后a++是错误的:数组名不可被赋值
  2. (C15A/C16A) For the declarations: char *s, str[10];, statement ____ is completely correct. A. strcpy(s, "hello"); B. str="hello"+1 C. s=*&(str+1) D. s=str+1

A. 将 "hello" 拷贝到 s 指向的空间。但是 s 指向什么呢?你并不清楚,也就是说 s 是一个野指针,你不清楚它指向哪里,也就自然不能向它指向的空间中写入数据 B. str 是一个数组,数组名不能被赋值,所以是错的 C. str+1 不能被取地址,因为这是计算过程中的一个数,而不是实际存在内存中的数,所以是错的 D. str+1 表示的就是 str 数组中第二个元素的地址,将其赋值给 s,是正确的

  1. 定义了char *a = "hello"之后,表示a作为字符指针指向了"hello"的开头,但是是只读的,是不可修改的

五. 奇怪表达式

以下代码语法正确的是_____A. for ( ); B. do { } while ( ); C. while ( ) ; D. for ( ; ; ) ;

注意这道题考的是空表达式而不是循环语句。while 后的括号中必须有条件表达式,所以 BC 错误;for 后面的括号中必须有两个分号分割的三个语句,所以 A 错误。 D 是正确的,for( ; ; ) 就表示死循环,而后面的 ; 表示循环体为空,语法完全正确,是一个彻底的死循环。

六. 文件相关

记住相关函数!

  • 打开文件:

    if((fp = fopen("48","rb"))==NULL){  
        printf("Error!");  
        exit(0);  
    }
    

  • 关上文件:

    if(fclose(fp)) {  
        printf("Cannot close\n");  
        exit(0);  
    }
    
    考点:失败是1,成功是0,(C14)

  • 读取文件:

    • 字符方式:
      • ch=fgetc(fp)
      • fputc(ch,fp)
    • 格式化方式:
      • fscanf(文件指针,格式字符串,输入表)
      • fprintf(文件指针,格式字符串,输出表)
    • 数据流
      • fread(数据所在的指针,sizeof(数据块),数据块数,文件指针fp)

七. 杂项

1. 设int i=0, j=9; char s[ ] = "happy new year!", *sp=s,*sq=s+9; 执行下列哪一条语句所得到的结果和其他三项不同_______.

A.while ( i <= j ) s[i++]=s[j--]; B.for ( ; i<=j; ++i, --j ) s[i]=s[j];
C.for ( ; sp++ <= sq--; ) *sp = *sq; D.do { *sp=*sq; } while( sp++ < sq--);

do-while 循环会执行一次,然后检查条件 sp < sq。由于 spsq 初始时相等(都指向 s[0]s[9]),条件为 false,循环不会执行任何操作,s 保持原样 "happy new year!"

  1. 函数可以嵌套调用但不能嵌套定义

Comments