Skip to content

problems and keys

Fall

  1. 假设某段C语言程序中定义了三个变量a、b和c并且三个变量都不为0,则表达式a / b * c和a * c / b是等价的,其值相同。(F)

    根据C语言的算术运算规则,表达式 `a / b * c` 和 `a * c / b` 并不总是等价的,其值可能不同。主要原因在于整数除法的截断行为(如果变量是整数类型)和浮点数的精度问题。
    
  2. What is the output of the following program?

int main()
{
      int  a = 2, b = -1, c = 2;
      if(a < b)
            if(b < 0)
                  c = 0;
      else  c++;
      printf("%d\n",c);
      return 0;
}

最终输出c的值是2没有改变。 本题考查C语言中else与if的配对规则:在C语言中,else总是与同一作用域内最近的、尚未匹配的if语句匹配。这个规则被称为"最近匹配原则"或"dangling else问题"的解决方案。

  1. Among the following statements which intend to define arrays, which one is wrong?

    A. `int x[2][]={1,2,4,6}`;
    B. `int m[][3]={1,2,3,4,5,6}`;
    C. `int a[1][3]`;
    D. `int x[2][2]={1,2,3,4}`;
    
    key: A
    在C语言中,定义多维数组时,只有第一维的大小可以省略(当有初始化列表时),但其他维度的大小必须明确指定。选项A中,`int x[2][]={1,2,4,6};` 的第二维为空,这是错误的,因为编译器无法确定第二维的大小,从而无法计算内存布局。
    
  2. 下列程序的输出结果是( ). A. (6,6) B. (3,6) C. (6,12) D. (3,3)

# include <stdio.h>

int f(int n){
    static int k, s;
    n--;
    for(k=n; k>0; k--)
        s += k;
    return s;
}

int main(void){
    int k;
    k=f(3);
    printf("(%d,%d)", k, f(k));
    return 0;
}
key: B 静态变量基本特点: 1. 生命周期:程序运行期间一直存在 2. 只初始化一次,默认初始化为0 3. 存储位置:静态存储区(数据段) 注意事项: 可能使函数不可重入 增加内存占用 测试时需要特殊处理

  1. 关于C语言指针的运算:指针只有加减操作,没有乘除操作。指针可以加常数、减常数;相同类型的指针可以相加、相减。(F)

    在C语言中,指针确实没有乘法和除法操作,但指针的加减操作是有限制的。指针可以加或减一个整数常数(表示移动指针到相邻内存位置),但相同类型的指针不能相加——指针相加是非法的,因为它在语义上没有意义(例如,两个地址相加无法得到有效地址)。相同类型的指针可以相减,得到的是两个指针之间的元素个数。
    
  2. The remainder operator (%) can be used only with integer operands. (T)

  3. The following code fragment prints out .

int a=2,b=9;
do{
    b-=a;
    a++;
}while(b--<0);
printf("a=%d,b=%d\n",a,b);
A.a=1,b=-1
B.a=2,b=8
C.a=3,b=6
D.a=3,b=7

key:C
1. 注意循环执行次数;
2. 注意循环条件的表达式的副作用.

Winter

  1. C语言中,编译预处理后,所有的符号常量名和宏名都用相应的字符串替换.(T) 符号常量指的是宏常量,const 定义的叫做常变量/只读变量.

  2. 随机操作只适用于二进制文件.(F) 文本文件也能使用 fseek 或 rewind(例如回到文件开头). 虽然二进制文件定位更精准(无换行符转换问题),但语法上随机操作并不排斥文本文件.

  3. The value of expression !("01/24/2019"+5)[5] is ? Key: 1. 字符串字面量退化为指向第一个字符 '0' 的地址的指针,先算小括号内的表达式,值为指向第二个 / 的指针, 再算 [5] ,值为指向字符串最后的 '\0' ,即 0,最后运算逻辑非,值为 1.

  4. For definitions: char s[2][3]=("ab" "cd"),*p=(char *)s; the expression ____ is correct and its value is equivalent to the element s[1][1]. A. *(s+3) B. *s+2 C. p[1][1] D. *++p+2

    Key: D.
    字符串在对字符数组初始化时不会退化为指针. s数组的初始化情况为
    | `'a'` | `'b'` | `'\0'` |
    | `'c'` | `'d'` | `'\0'` |
    (实际上在内存中顺序排列)
    `s[1][1]` 的值即为 `'d'`.
    表达式 `*p=(char *)s` 中,s首先退化为指向第一个3元数组首地址的指针,即 `&s[0]` ,再被显式类型转换为字符指针,即 `&s[0][0]` (地址是相同的,只是指针的步长和指向地址存储的数据类型改变了),赋值给 p.
    
    A 表示对不存在的 s 二维数组第四行解引用的结果,是 UB;
    
    B `*s` 等价于 `s[0]` ,即得到二维数组 s 的第一行的数组,表达式中进一步退化为指向数组首地址的指针,即 `&s[0][0]` ,则原表达式等价于 `&s[0][0]+2`,得到指向 `'\0'` 地址的指针.
    
    C p 只是一个一级字符指针,不能进行两次 `[]` 运算,会编译错误.
    
    D 先算 `++p` 得到 `&s[0][1]` ,再解引用,得到 `'b'` ,最后 `+2` 得到 `'d'` 正确.
    
  5. The following code fragment will output _____.

    char *week[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}, **pw = week;
    char c1, c2;
    c1 = (*++pw)[1];
    c2 = *++pw[1];
    printf("%c#%c#",c1,c2);
    

    Key: u#e# 注意表达式的副作用,对c1赋值的表达式中移动了pw指针.

  6. 鹤翔万里50题