那些年,做错的C语法题
2014-03-06 09:07
134 查看
语法题目考察的比较集中,基本上包括以下几个方面:
宏定义和预处理
结构体、功用体对齐、长度
sizeof/typedef
变量类型转换
指针运算
关键字
运算符优先级
语法解析
1、写出下列代码的运行结果:
答:var1 = var2/nvar2 = var1/n
析:#为字符串化操作符,讲锁连接的部分转化为一个字符串,##为字符串连接符,将两个字符串连接成一个字符串,均在预处理时完成字符串的替换。仔细点,应该错不了。
2、写出下列代码的运行结果:
答:12和f(1,2)。
析:本题考察字符串化操作符#得作用得执行过程,以及宏定义替换的次序。如果该宏为带#号的宏定义,则直接替换字符串,无需再嵌套替换,如果该宏不是带#的宏,则先替换括号内部的宏定义,然后替换外部的。
3、定义一个宏,求一个结构体struct中某个变量相对于struct的偏移量
1、写出输出结果:
答:value c =2/nvalue c=3/n
析:此处q-p=2,容易错,地址相减得除以类型,表面上差了8,实际上差了2。不同类型的地址,比如char *p,额int *p,p-q不能操作,报错。
2、写出下列函数运行结果:
答:结果为2,5
3、假如我们的a的地址是:0Xbfe2e100, 而且是32位机,那么这个程序会输出什么?
结果:0Xbfe2e100,0Xbfe2e104,0Xbfe2e100,0Xbfe2e114。
分析:分清除哪个表示数组结构,哪个表示数组元素,a表示第一个元素的地址,&a表示数组结构的地址。
1、一个指向有10个整型数数组的指针(Apointertoanarrayof10integers)
一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer)
答:int (*a)[10];int (*fn)(int);
2、const关键字的作用:
constinta;
intconsta;
constint*a;
int*consta;
intconst*aconst;
答:const一直理解的和初学者一样,什么东西被const修饰了,就只读了,无论你修饰的是变量、返回值或者指针。上面分别代表:
整形常量a,a的值只读;
整形常量a,a的值只读;
整形常量指针a,*a的值只读,a可以修改;
整形常量指针a,a的值只读,*a可以修改;
整形常量指针a,a的值只读,*a也只读;
3、写出打印结果:
答:0 0 1 1。
析:虽然都是常量,但是数组有空间,指针没空间。
4、volatile关键字什么用处?
答:volatile关键字修饰变量,提示编译器该变量是“易变”的,在执行与该变量有关的操作时,需要从变量中取值,而不要仅仅从寄存器中取,常用的情况有,状态寄存器变量、并发共享变量等等。
1、下列代码输出是:
答:>6。
析:主要考察不同类型的变量在一块运行的转化原则:有符号要向无符号的方向转化。因此>6。
2、下列操作没有任何打印,原因?
#include <stdio.h>
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23,34,12,17,204,99,16};
int main()
{
int d;
for(d=-1;d <= (TOTAL_ELEMENTS-2);d++)
printf("%dn",array[d+1]);
return 0;
}
答:由于TOTAL_ELEMENTS得出结果后为unsignedint类型,与-1比较时,将-1转化为无符号整形,也即0xFFFFFFFF,不满足条件退出。
1、写出结果
答:a=6,b=7,c=12。
析:这个题目考察语法解析。表面上可以理解为a++ + b,也可以理解为a+ ++b,因为编译器解析关键字是从左向右的,尽量包含更多的字符组成关键字,称为“贪心法”或者“大嘴法”。
2、A、B、C、D的运算结果分别是:
答:前两个9,10没问题,后两个gcc报错左值问题。但网上有人说D位11
析:本题考察左值运算,即等号左面的不能是一个数,可以是变量。
3、写出运算结果:
答:25,81。
析:相当于b1=((a++)*(a++)),b2=((++a)*(++a))。编译器编译时,a++先用再加(所为先用再加,应该是=后面的部分),而++a,是先加再用。
4、写出结果
答:8
分析:本题目考察&&短路径求解问题,所为短路求值:对于(条件1 && 条件2),如果“条件1”是false,那“条件2”的表达式会被忽略了。对于(条件1 || 条件2),如果“条件1”为true,而“条件2”的表达式则被忽略了。
5、写出程序运行结果:
答:11,10,11,11。
1、下列代码执行结果:
答:32为系统52,64位系统64.
分析:关于对齐,32位默认4byte对齐,64位默认8byte对齐,或者通过#pragma pack(N)来实现执行对齐。union共享功用体最长的空间,而struct是各成员空间相加。
2、下列代码运行结果:
答:1
分析:正因为sizeof是编译期求值的,所以如果它跟着表达式,那么表达式是不被计算的,只是根本表达式的类型得到它占用的空间。
1、一语句实现x是否为2的若干次幂的判断(32位系统)
转载地址:http://www.kuqin.com/shuoit/20140104/337415.html
宏定义和预处理
结构体、功用体对齐、长度
sizeof/typedef
变量类型转换
指针运算
关键字
运算符优先级
语法解析
一、宏定义和预处理
1、写出下列代码的运行结果:1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #include <stdio.h> #define STRCPY(a, b) strcpy(a ## _p, #b) int main() { char var1_p[20]; char var2_p[30]; strcpy (var1_p, "aaaa" ; strcpy (var2_p, "bbbb" ; STRCPY(var1, var2); STRCPY(var2, var1); printf ( "var1 = %s/n" , var1_p); printf ( "var2 = %s/n" , var2_p); return 0; } |
析:#为字符串化操作符,讲锁连接的部分转化为一个字符串,##为字符串连接符,将两个字符串连接成一个字符串,均在预处理时完成字符串的替换。仔细点,应该错不了。
2、写出下列代码的运行结果:
1 2 3 4 5 6 7 8 9 10 | #include <stdio.h> #define f(a,b) a##b #define g(a) #a #define h(a) g(a) int main() { printf ( "%sn" , h(f(1,2))); printf ( "%sn" , g(f(1,2))); return 0; } |
析:本题考察字符串化操作符#得作用得执行过程,以及宏定义替换的次序。如果该宏为带#号的宏定义,则直接替换字符串,无需再嵌套替换,如果该宏不是带#的宏,则先替换括号内部的宏定义,然后替换外部的。
3、定义一个宏,求一个结构体struct中某个变量相对于struct的偏移量
1 | #define OFFSET(struct, member) ((unsignedint)&((struct *)0)->member) |
二、指针运算
1、写出输出结果:1 2 3 4 5 6 7 8 9 10 11 12 13 14 | int main() { int a[3]; a[0] = 0; a[1] = 1; a[2] = 2; int *p, *q; p = a; q = &a[2]; int c = a[q - p]; printf ( "value c = %d/n" , c++); printf ( "value c = %d/n" , c); return 0; } |
析:此处q-p=2,容易错,地址相减得除以类型,表面上差了8,实际上差了2。不同类型的地址,比如char *p,额int *p,p-q不能操作,报错。
2、写出下列函数运行结果:
1 2 3 4 5 6 7 | #incude <stdio.h> void main() { int a[5]={1,2,3,4,5}; int *ptr=( int *)(&a+1); printf ( "%d,%d" ,*(a+1),*(ptr-1)); } |
3、假如我们的a的地址是:0Xbfe2e100, 而且是32位机,那么这个程序会输出什么?
1 2 3 4 5 6 7 8 9 10 | #include <stdio.h> int main() { int a[5]; printf ( "%xn" , a); printf ( "%xn" , a+1); printf ( "%xn" , &a); printf ( "%xn" , &a+1); return 0; } |
分析:分清除哪个表示数组结构,哪个表示数组元素,a表示第一个元素的地址,&a表示数组结构的地址。
三、关键字
1、一个指向有10个整型数数组的指针(Apointertoanarrayof10integers)一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer)
答:int (*a)[10];int (*fn)(int);
2、const关键字的作用:
constinta;
intconsta;
constint*a;
int*consta;
intconst*aconst;
答:const一直理解的和初学者一样,什么东西被const修饰了,就只读了,无论你修饰的是变量、返回值或者指针。上面分别代表:
整形常量a,a的值只读;
整形常量a,a的值只读;
整形常量指针a,*a的值只读,a可以修改;
整形常量指针a,a的值只读,*a可以修改;
整形常量指针a,a的值只读,*a也只读;
3、写出打印结果:
1 2 3 4 5 6 7 8 9 10 11 12 | char str1[] = "abc" ; char str2[] = "abc" ; const char str3[] = "abc" ; const char str4[] = "abc" ; const char *str5 = "abc" ; const char *str6 = "abc" ; char *str7 = "abc" ; char *str8 = "abc" ; cout << ( str1 == str2 ) << endl; cout << ( str3 == str4 ) << endl; cout << ( str5 == str6 ) << endl; cout << ( str7 == str8 ) << endl; |
析:虽然都是常量,但是数组有空间,指针没空间。
4、volatile关键字什么用处?
答:volatile关键字修饰变量,提示编译器该变量是“易变”的,在执行与该变量有关的操作时,需要从变量中取值,而不要仅仅从寄存器中取,常用的情况有,状态寄存器变量、并发共享变量等等。
五、类型强制转换
1、下列代码输出是:1 2 3 4 5 6 7 8 9 10 11 12 | #include <stdio.h> void foo( void ) { unsigned int a = 6; int b = -20; (a+b > 6)? puts ( "> 6" ) : puts ( "<= 6" ); } int main() { foo(); return 0; } |
析:主要考察不同类型的变量在一块运行的转化原则:有符号要向无符号的方向转化。因此>6。
2、下列操作没有任何打印,原因?
#include <stdio.h>
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23,34,12,17,204,99,16};
int main()
{
int d;
for(d=-1;d <= (TOTAL_ELEMENTS-2);d++)
printf("%dn",array[d+1]);
return 0;
}
答:由于TOTAL_ELEMENTS得出结果后为unsignedint类型,与-1比较时,将-1转化为无符号整形,也即0xFFFFFFFF,不满足条件退出。
六、优先级与左值
1、写出结果1 2 3 4 5 6 7 8 | #include <stdio.h> int main() { int a = 5, b = 7, c; c = a+++b; printf ( "a=%d,b=%d,c=%dn" ,a,b,c); return 0; } |
析:这个题目考察语法解析。表面上可以理解为a++ + b,也可以理解为a+ ++b,因为编译器解析关键字是从左向右的,尽量包含更多的字符组成关键字,称为“贪心法”或者“大嘴法”。
2、A、B、C、D的运算结果分别是:
1 2 3 4 5 | int a = 4; (A) a += (a++); (B) a += (++a) ; (C) (a++) += a; (D) (++a) += (a++); |
析:本题考察左值运算,即等号左面的不能是一个数,可以是变量。
3、写出运算结果:
1 2 3 4 5 6 7 8 9 10 11 | #include <stdio.h> #define SQUARE(a) ((a)*(a)) int main( void ) { int a=5; int b1,b2; b1 = SQUARE(a++); b2 = SQUARE(++a); printf ( "b1=%d, b2=%dn" ,b1,b2); return 0; } |
析:相当于b1=((a++)*(a++)),b2=((++a)*(++a))。编译器编译时,a++先用再加(所为先用再加,应该是=后面的部分),而++a,是先加再用。
4、写出结果
1 2 3 4 5 6 7 | int main() { int i = 6; if ( ((++i < 7) && ( i++/6)) || (++i <= 9)); printf ( "%dn" ,i); return 0; } |
分析:本题目考察&&短路径求解问题,所为短路求值:对于(条件1 && 条件2),如果“条件1”是false,那“条件2”的表达式会被忽略了。对于(条件1 || 条件2),如果“条件1”为true,而“条件2”的表达式则被忽略了。
5、写出程序运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #include<stdio.h> int f( int n) { return ++n; } int g( int *n) { return ++*n; } main () { int n=10; int k=0; k=f(n); printf ( "k is: %dn" , k); printf ( "n is: %dn" , n); k=g(&n); printf ( "k is: %dn" , k++); printf ( "n is: %dn" , n++); } |
七、类型长度
1、下列代码执行结果:1 2 3 4 | typedef union {long i; int k[5]; char c;} DATE ; struct data { int cat; DATE cow; double dog;} too; DATE max; printf( "%d" ,sizeof(struct date )+sizeof(max)); |
分析:关于对齐,32位默认4byte对齐,64位默认8byte对齐,或者通过#pragma pack(N)来实现执行对齐。union共享功用体最长的空间,而struct是各成员空间相加。
2、下列代码运行结果:
1 2 3 4 5 6 7 8 | #include <stdio.h> int main() { int i = 1; sizeof (i++); printf ( "%dn" , i); return 0; } |
分析:正因为sizeof是编译期求值的,所以如果它跟着表达式,那么表达式是不被计算的,只是根本表达式的类型得到它占用的空间。
八、其他
1、一语句实现x是否为2的若干次幂的判断(32位系统)1 | x|(x-1)=0xFFFFFFFF? puts ( "true" ): puts ( "false" ); |
相关文章推荐
- 那些年我做错的笔试题一
- 致那些年追寻C语言编程的青春, 从语法, 到界面, 再到算法, 只有这些了
- 批处理文件bat 语法备忘
- Lua脚本语法说明(修订)
- 黑马程序员 abstract class和interface语法区别
- 前端开发利器 Emmet 介绍与基础语法教程
- smali文件语法参考
- 《黑马程序员》Java环境变量配置和基础语法
- jquery语法
- python使用小语法---持续更新
- C语言快速学习笔记001-相关语法
- css样式标签和js语法属性区别
- linq to sql 语法 学习笔记(2)
- 《那些年啊,那些事——一个程序员的奋斗史》——40
- 存储过程语法
- 拾遗:Perl 基础语法
- Linq语法新特性
- python2 与 python3 语法区别
- Apache2.4和Apache2.2访问控制配置语法对比
- Python中的with…as…语法