做错过的C语法题目

语法题目考察的比较集中,基本上包括以下几个方面:
宏定义和预处理
结构体、功用体对齐、长度
sizeof/typedef
变量类型转换
指针运算
关键字
运算符优先级
语法解析
需要认证啊,错很多基础的。本篇博客耗时4小时。
一、宏定义和预处理

1、写出下列代码的运行结果:

#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;
}

答:var1 = var2

       var2 = var1

析:#为字符串化操作符,将所连接的部分转化为一个字符串,##为字符串连接符,将两个字符串连接成一个字符串,均在预处理时完成字符串的替换。仔细点,应该错不了。


2、写出下列代码的运行结果:

#include <stdio.h>
#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)
int main()
{
printf("%s\n", h(f(1,2)));
printf("%s\n", g(f(1,2)));
return 0;
}

答:12

       f(1,2)

析:本题考察字符串化操作符#的作用的执行过程,以及宏定义替换的次序。如果该宏为带#号的宏定义,则直接替换字符串,无需再嵌套替换,如果该宏不是带#的宏,则先替换括号内部的宏定义,然后替换外部的。


3、定义一个宏,求一个结构体struct中某个变量相对于struct的偏移量

#define OFFSET(struct, member) ((unsigned int)&((struct *)0)->member)

二、指针运算
1、写出输出结果:

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;
}

答:value c=2

       value c=3

析:此处q-p=2,容易错,地址相减得除以类型,表面上差了8,实际上差了2。不同类型的地址,比如char *p和int *q,p-q不能操作,报错。


2、写出下列函数运行结果:

#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));
}
答:结果为2,5


3、假如我们的a的地址是:0Xbfe2e100, 而且是32位机,那么这个程序会输出什么?

#include <stdio.h>
int main()
{
int a[5];
printf("%x\n", a);
printf("%x\n", a+1);
printf("%x\n", &a);
printf("%x\n", &a+1);
return 0;
}
结果:0Xbfe2e100,0Xbfe2e104,0Xbfe2e100,0Xbfe2e114。

分析:分清除哪个表示数组结构,哪个表示数组元素,a表示第一个元素的地址,&a表示数组结构的地址


三、关键字
1、一个指向有10个整型数数组的指针(Apointer to an array of 10 integers)

      一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer)


答:int (*a)[10];int (*fn)(int);


2、const关键字的作用:
const int a;
int const a;
const int *a;
int * const a;
int const *a const;


答:const一直理解的和初学者一样,什么东西被const修饰了,就只读了,无论你修饰的是变量、返回值或者指针。上面分别代表:


整形常量a,a的值只读;

整形常量a,a的值只读;

整形常量指针a,*a的值只读,a可以修改;

整形常量指针a,a的值只读,*a可以修改;

整形常量指针a,a的值只读,*a也只读。


3、写出打印结果:

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;


答:0 0 1 1。

析:虽然都是常量,但是数组有空间,指针没空间。


4、volatile关键字什么用处?


答:volatile关键字修饰变量,提示编译器该变量是“易变”的,在执行与该变量有关的操作时,需要从变量中取值,而不要仅仅从寄存器中取,常用的情况有,状态寄存器变量、并发共享变量等等。


五、类型强制转换

1、下列代码输出是:

#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。

析:主要考察不同类型的变量在一块运行的转化原则:有符号要向无符号的方向转化。因此>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("%d\n",array[d+1]); 
 return 0;
}


答:由于TOTAL_ELEMENTS得出结果后为unsigned int类型,与-1比较时,将-1转化为无符号整形,也即0xFFFFFFFF,不满足条件退出。


六、优先级与左值

1、写出结果
#include <stdio.h>
int main()
{
int a = 5, b = 7, c;
c = a+++b;
printf("a=%d,b=%d,c=%d\n",a,b,c);
return 0;
}
答:a=6,b=7,c=12。
析:这个题目考察语法解析。表面上可以理解为a++ + b,也可以理解为a+ ++b,因为编译器解析关键字是从左向右的,尽量包含更多的字符组成关键字,称为“贪心法”或者“大嘴法”。
2、A、B、C、D的运算结果分别是:

int a = 4;
(A) a += (a++);
(B) a += (++a) ;
(C) (a++) += a;
(D) (++a) += (a++);

答:前两个9,10没问题,后两个gcc报错左值问题。但网上有人说D位11
析:本题考察左值运算,即等号左面的不能是一个数,可以是变量。

3、写出运算结果:

#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=%d",b1,b2);
return 0;
}


答:25,81。

析:相当于b1=((a++)*(a++)),b2=((++a)*(++a))。编译器编译时,a++先用再加(所为先用再加,应该是=后面的部分),而++a,是先加再用。


4、写出结果

int main()
{
int i = 6;
if( ((++i < 7) && ( i++/6)) || (++i <= 9));
printf("%d\n",i);
return 0;
}
答:8
分析:本题目考察&&短路径求解问题,所为短路求值:对于(条件1 && 条件2),如果“条件1”是false,那“条件2”的表达式会被忽略了。对于(条件1 || 条件2),如果“条件1”为true,而“条件2”的表达式则被忽略了。


5、写出程序运行结果:

#include<stdio.h>
int f(int n)
{
return ++n;
}
int g(int *n)
{
return ++*n;
}
main ()
{
        int n=10;
<span style="white-space:pre">	</span>int k=0;
<span style="white-space:pre">	</span>k=f(n);
<span style="white-space:pre">	</span>printf ("k is: %d\n", k);
<span style="white-space:pre">	</span>printf ("n is: %d\n", n);
<span style="white-space:pre">	</span>k=g(&n);
<span style="white-space:pre">	</span>printf ("k is: %d\n", k++);
<span style="white-space:pre">	</span>printf ("n is: %d\n", n++);
}
答:11,10,11,11。


七、类型长度

1、下列代码执行结果:

typedef union {long i; int k[5]; char c;} DATE;
struct data { int cat; DATE cow; double dog;};
DATE max;
printf("%d",sizeof(struct data)+sizeof(max));
答:32为系统52,64位系统64.
分析:关于对齐,32位默认4byte对齐,64位默认8byte对齐,或者通过#pragma pack(N)来实现执行对齐。union共享功用体最长的空间,而struct是各成员空间相加。


2、下列代码运行结果:

#include <stdio.h>
int main()
{
int i = 1;
sizeof(i++);
printf("%d\n", i);
return 0;
}
答:1
分析:正因为sizeof是编译期求值的,所以如果它跟着表达式,那么表达式是不被计算的,只是根本表达式的类型得到它占用的空间。


八、其他

1、一语句实现x是否为2的若干次幂的判断(32位系统)
x|(x-1)=0xFFFFFFFF?puts("true"):puts("false");


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值