当前位置:   article > 正文

C语言笔试一些简单容易错的题目_void main() {intm=6; if(m++>5)printf("%d\n",m); el

void main() {intm=6; if(m++>5)printf("%d\n",m); else printf("%d\n",m--);

1.字符串反转,比如输入abcd123,然后编程321dcba

  1. #include<stdio.h>
  2. #include<string.h>
  3. int main(void)
  4. {
  5. char buf[10];
  6. char t;
  7. int len;
  8. puts("enter a string:");
  9. fgets(buf,sizeof(buf),stdin);
  10. puts("before:");
  11. puts(buf);
  12. len=strlen(buf);
  13. for(int i=0;i<len/2;i++)
  14. {
  15. t=buf[i];
  16. buf[i]=buf[len-1-i];
  17. buf[len-1-i]=t;
  18. }
  19. puts("after:");
  20. puts(buf);
  21. return 0;
  22. }

注意:fgets(scanf函数不能接受空格,而fgets函数可以)函数第一个参数是缓冲区buf,第二个是buf-1的大小,因为我们还有一个“\0”要占最后一个字节。字符串反转大概思路就是:第一个字符串和最后一个字符串对调,第二个字符串和最后一个字符串对调,这样依次完成,因为我们最后一个字符是结束符,所以要在for循环里面-1;

2.define宏定义

  1. #include<stdio.h>
  2. #include<string.h>
  3. #define M 5
  4. #define N M+M
  5. int main(void)
  6. {
  7. int k;
  8. k=N*N*5; //M+M*M+M*5 5+25+25
  9. printf("%12d\n",k);
  10. return 0;
  11. }

当时做错的原因:define N  M+M  ,M=5;我把M+M算出来,不能这样,是N替换M+M,只要遇到N就替换为M+M,而不是把M+M算出来为10;

3.++ i 是先加后赋值;i ++ 是先赋值后加;++i和i++都是分两步完成的

  1. #include<stdio.h>
  2. #include<string.h>
  3. int main(void)
  4. {
  5. int m=5;
  6. if(m++>5)
  7. printf("%d\n",m);
  8. else
  9. printf("%d\n",--m);
  10. return 0;
  11. }

m++>5,是先赋值,也就是先在if里面判断,然后再++;判断m没有大于5,执行else,然后--m;--是先减,然后再赋值,m在上面++过了,变成了6,在下面是--m,然后再赋值,所以结果是5。如果是是m--,那么结果就是6,先赋值,再减。

4.指针和i++

  1. #include<stdio.h>
  2. #include<string.h>
  3. int a[]={0,2,4,6,8};
  4. int main(void)
  5. {
  6. int i;
  7. int *p=a;
  8. for(i=0;i<4;i++)a[i]=*p++;
  9. printf("%d\n",a[2]);
  10. return 0;
  11. }

解释:*p++就相当于*(p++),p先与++结合,然后p++整体再与*结合。*p++解析:++先跟p结合,但是因为++后置的时候,本身含义就是先运算后加1(运算指的是整体与前面的*进行运算;加1指的是p+1),所以实际上*p++符号整体对外表现的值是*p的值,运算完成后p再加1;等同于:*p,p+=1;

(*p)++这个的意思是:先去处p里面的值赋值给人家,再把p里面的值+1;

5.

  1. void foo(void) {
  2. unsigned int a = 6;
  3. int b = -20;
  4. (a+b > 6) puts("> 6") : puts("<= 6")
  5. }输出的是什么

unsigned 是无符号数。 b 是有符号数负数,无符号数和有符号数混合运算 要注意 你到底 想计算什么。默认,把有符号数内容 当成无符号数解释 计算。-20 就当 0xffffffec (4294967276).显然(a+b > 6) 成立。输出 > 6。

6.三目运算符也叫条件运算符

如果希望获得两个数中最大的一个,可以使用 if 语句,例如:

if(a>b){
    max = a;
}else{
    max = b;
}

不过,C语言提供了一种更加简单的方法,叫做条件运算符,语法格式为:

表达式1 ? 表达式2 : 表达式3

运算规则是这样的:如果表达式1的值为真,则以表达式2 的值作为整个条件表达式的值,否则以表达式3的值作为整个条件表达式的值。

上面的 if else 语句等价于:

max = (a>b) ? a : b;  //a>b,就输出a,否则输出b

我们来看一道面试题

问题:写一个”标准"宏MIN ,这个宏输入两个参数并返回较小的一个。

#define Min(a,b) ( ((a)>=(b)) ? (b) : (a) )  

7.关键字const是什么含意?

  1. const int a;
  2.   int const a;
  3.   const int *a;
  4.   int * const a;
  5.   int const * a const;

首先理解一下 const int *a 和int *const a,去掉int,变成 const *a, 这样理解const 修饰 *a,*a就是a所指的那个数字,就是那个数字不能被改变。这样就比较好理解int *const a,去掉int,const修饰a,a是指针(里面存的地址)也就是里面的地址不能不改变。前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。

8.指针与指针相减

我们直接来看这道题,老爱忘记。

  1. #include<stdio.h>
  2. int main(void)
  3. {
  4. int *p1,*p2,a[10];
  5. p1=a;
  6. p2=&a[5];
  7. printf("%d\n",p2-p1);
  8. return 0;
  9. }

解析:任何编译器上都是5。指针减法含义:两个地址之间有多少个计量单位,那么p2-p1的意思就是p2和p1之间有多少个int,那么不管in是16位,还是32位,甚至是64位,和int的长度没有关系。

9.中断问题

中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准C支持中断,从而产生了一个新的关键字 __interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码。

__interrupt double compute_area (double radius)

{

double area = PI * radius * radius;

printf("\nArea = %f", area);

return area;

}

答: aISR不能返回一个值。

        bISR不能传递参数。

        c、在许多处理器编译器中,浮点一般都是不可冲入的。有些处理器编译器需要让额外的寄存器入栈,有些处理器编译器就不允许在ISR中做浮点运算。此外ISR应该是短而有效率的。在ISR中做浮点运算是不明智的。

        dprintf经常是有冲入性和性能上的问题,所以一般不使用printf函数

10.++前置++后置

  1. #include<stdio.h>
  2. int main(int argc, char *argv)
  3. {
  4. int a = 1, b = 1;
  5. int aplus, bplus;
  6. aplus = a++; //先把a的值赋值给aplus,a再加1
  7. bplus = ++b; //b的值先加1, 再把值赋值给bplus
  8. printf("a aplus b bplus\n");
  9. printf("%d %d %d %d\n", a, aplus, b , bplus);
  10. return 0;
  11. }

程序运行如下:

a aplus b bplus
2   1     2    2

  1. #include<stdio.h>
  2. #define TEN 10
  3. int main(int argc, char *argv)
  4. {
  5. int n = 0;
  6. while (n++ < TEN)
  7. printf("%5d",n);
  8. printf("\n");
  9. return 0;
  10. }

程序运行如下:

    1    2    3    4    5    6    7    8    9   10

分析 :这里是先比较大小再加1, n一开始为0,0小于10,n+1,输入1,一直加到9小于10,9+1,所以输出10

  1. #include<stdio.h>
  2. #define TEN 10
  3. int main(int argc, char *argv)
  4. {
  5. int n = 0;
  6. while (++n < TEN)
  7. printf("%5d",n);
  8. printf("\n");
  9. return 0;
  10. }

程序运行如下:

    1    2    3    4    5    6    7    8    9

分析:这里是先比较大小,再+1,相当于n = n+1;

11.指针偏移量的问题

  1. #include <stdio.h>
  2. int main()
  3. {
  4. int a[] = {1, 2, 3, 4, 5};
  5. int *p = (int *)(&a + 1);
  6. printf("%d %d \n", *(p - 1), *p - 1);
  7. printf("%ld %ld\n", sizeof(a), sizeof(&a));
  8. return 0;
  9. }

12.指针指向常量区

str1和st2的地址是不是一样的,结果是一样的为什么呢?

  1. #include <stdio.h>
  2. int main()
  3. {
  4. char *str1 = "hello world";
  5. char *str2 = "hello world";
  6. printf("%p\n", str1);
  7. printf("%p\n", str2);
  8. char *str3 = str2;
  9. str3 = "NICE";
  10. printf("%s\n", str3);
  11. printf("%s\n", str2);
  12. return 0;
  13. }

13.函数返回值一样吗?第二个会发生段错误

  1. #include <stdio.h>
  2. char* get_hello1();
  3. char* get_hello2();
  4. int main()
  5. {
  6. printf("%s\n",get_hello1());
  7. printf("%s\n",get_hello2());
  8. return 0;
  9. }
  10. char *get_hello1()
  11. {
  12. char *str1 = "hello";
  13. return str1;
  14. }
  15. char *get_hello2()
  16. {
  17. char str2[] = "hello";
  18. return str2;
  19. }

14.指针的偏移量

  1. #include<stdio.h>
  2. int main(int argc, char *argv[])
  3. {
  4. int a[] = {384, 385, 386};
  5. char *p = (char *)a;
  6. printf("%d\n", *p);
  7. printf("%d\n", *(p + 1));
  8. printf("%d\n", *(p + 4));
  9. return 0;
  10. }

简单分析一下:大概意思就是4个字节,转换成1个字节。384的二进制是1 1000 0000,只取低8位就是1000 0000,也就是-128,*(p+1)就是指针移动1个字节,也就是到1的地方,结果就是1。

运行结果如下:

-128
1
-127

15.一道很不错的题目,对于复习大小端,和内存分布,指针偏移很有帮助。

  1. #include<stdio.h>
  2. /* 小端模式 */
  3. int main(int argc, char *argv)
  4. {
  5. int a[4] = {1, 2 ,3, 4};
  6. int *p1 = (int *)(&a + 1);
  7. int *p2 = (int *)((char *)&a + 1);
  8. printf("0x%x, 0x%x\n", *(p1-1), *p2);
  9. return 0;
  10. }

先复习一下知识点,有点忘记了

a+1:就是数组首地址加上一个元素所占的地址大小,这里int是4个字节,所以加上1x4.
&a+1:代表的是加上整个数组的大小,这里数组尺寸是4,所以+1代表的是地址加上4x4.为了更好理解,画内存图来分析理解

 在这里插入图片描述

结果是0x4和0x2000000,0x2000000有点想不明白,看了“int *类型指针变量强制转换为char *的结果”,的博客就明白了,博客地址:

(85条消息) int *类型指针变量强制转换为char *的结果_肘子君的博客-CSDN博客_int指针强制转换成char指针

假如有这么一个程序

  1. int a = 0x44332211;
  2. int *p1 = &a;
  3. char *p2 = (char *)&a;
  4. printf("*p1 = 0x%x\n",*p1);
  5. printf("*p2 = 0x%x\n",*p2);

结果如下图

在这里插入图片描述

分析:
a,p1,p2在内存中的实际效果如下(地址是假设的)

p1和p2所指向的都是变量a的地址。

不同的地方在解指针的时候。
p1在解指针时,将0x00当作是四个字节的内存空间大小的首地址。然后以int的解析类型进行解析。也就是说在解指针时会将从0x00为起始的后面总共四个地址所包含的内存空间的数都以int的解析类型解析出来。
p2在解指针时,将0x00当作是一个字节的内存空间大小的首地址。然后以char的解析类型进行解析。也就是说在解指针时会将从0x00为起始的后面总共一个地址所包含的内存空间的数都以char的解析类型解析出来。

0x44332211在变量a指向的内存空间中的分布。
在这里插入图片描述

 *p1取a中的值时:四个字节作为整体一起解指针

在这里插入图片描述

 *p2取a中的值时:对一个字节的空间大小进行解指针

在这里插入图片描述

 由于p1和p2的指针类型不同。所以在对p1和p2做+1操作时,效果也会不同。
p1+1后,p1+1指向的内存地址为0x00+4=0x04;
p2+1后,p2+1指向的内存地址为0x00+1=0x01;

16.字符串大写字母转小写字母,代码比较简单,忘记的话就需要看一下ascii码

  1. #include<stdio.h>
  2. #include<string.h>
  3. int main()
  4. {
  5. int i, len;
  6. char s[101] = {0};
  7. gets(s);
  8. len = strlen(s);
  9. //大写变小写
  10. for(i = 0; i < len; i++) {
  11. if(s[i] >= 'A' && s[i] <= 'Z') {
  12. s[i] = s[i] + 32; /* 不明白就看一下ASCII码 */
  13. }
  14. }
  15. puts(s);
  16. return 0;
  17. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/215323
推荐阅读
相关标签
  

闽ICP备14008679号