事情是这样的,昨晚晚上,有个网友发消息给我,说他有几道C语言笔试题不会写,所以,就出现了解题的这一幕。
文章中,我只讲解了一部分,有一些题目觉得没必要讲,然后我在pdf上做了注释,想看的在公众号留言「20201227」获取pdf文档。
1、第一题
#include "stdio.h"int x = 2;
int y = 0; int main()
{if(x){y++;}printf("%d\n",y);getchar();return 0;
}
这是送分题,就没有怎么好说的了,答案 1 .
2、解析一道比较有坑的。
#include "stdio.h"
#include "string.h"int a()
{static int i =0;if(i>=1){return --i;}return i++;
}int main()
{int A1 = 0;int A2 = 0;int A3 = 0;A1 = a();A2 = a();A3 = a();printf("%d,%d,%d\n",A1,A2,A3);getchar();return 0;
}
这个题目,主要要搞清楚,return i++
,是先return i
再++
,那就问题不大了。
3、这题应该好好说一下
#include "stdio.h"int arg[] = {0,1,2,3};
int *p = &arg[1];
int v = 0;
int w = 0;int main()
{int i;*(p++)+= 5;v = *p; *p = *p +5;w=*p;printf("v:%d\n",v);printf("w:%d\n",w);for(i=0;i<4;i++)printf("arg[%d]=%d\n",i,arg[i]);getchar();return 0;
}
这题乍一看其实没有什么难度,但是实际写的时候,容易出问题,特意拿出来说一下。
核心在这行代码 *(p++)+= 5;
分解出来就是 取得p指向的值,然后 +=5
,再让p指向下一个位置。
反汇编代码是这样的
mov rax,QWORD PTR [rip+0x2f0f] # 404040 <p>
lea rdx,[rax+0x4] //这是让指针指向下一个位置保存的寄存器
mov QWORD PTR [rip+0x2f04],rdx # 404040 <p>
mov edx,DWORD PTR [rax] //这是用来也 5 运算的寄存器
add edx,0x5
mov DWORD PTR [rax],edx
如果知道了这点,其他的就容易很多了。
int i;*(p++)+= 5; //arg[1] = 6 p指向arg[2]v = *p; //v = arg[2] = 2*p = *p +5; //arg[2] = 2+5 = 7w=*p; //w = 7printf("v:%d\n",v);printf("w:%d\n",w);
大家可以自己试试,如果把 *(p++)+= 5
改成 *(++p)+= 5
结果如何呢?
4、链表编程题
下面的题目我只写了第一题,后面的一题没有继续下,写链表的题目,我建议画一张链表的连接图,这样写代码的时候就会特别清晰了。
大家有不懂的,可以尽管问,另一个题目,欢迎留言写出来,我觉得这样的题目简单,但是也比较考验思维能力。
题目:
链表图形
直接上代码吧
#include "stdio.h"
#include "string.h"
#include "stdlib.h"typedef struct _STUDENT_INFO
{int IDx;char Name[32];struct _STUDENT_INFO *Next;
} STUDENT_INFO_DEF;STUDENT_INFO_DEF * creat(void)
{STUDENT_INFO_DEF * h = (STUDENT_INFO_DEF *)malloc(sizeof(STUDENT_INFO_DEF));h->Next = NULL;return h;
}int InsertStu(STUDENT_INFO_DEF *head,STUDENT_INFO_DEF stu)
{if(head == NULL){printf("head NULL\n");return -1;}STUDENT_INFO_DEF * temp = head;STUDENT_INFO_DEF * new = (STUDENT_INFO_DEF *)malloc(sizeof(STUDENT_INFO_DEF));new->IDx = stu.IDx;strncpy(new->Name,stu.Name,strlen(stu.Name));new->Next = NULL;while (temp->Next != NULL) {temp=temp->Next;}temp->Next = new;printf("[InsertStu] IDx:%d Name:%s Ok\n",new->IDx,new->Name);return (0);
}/*遍历链表*/
int TraverseStu(STUDENT_INFO_DEF *head)
{STUDENT_INFO_DEF * temp = head;if(head == NULL){printf("head NULL\n");return -1;}while(temp->Next!=NULL){temp = temp->Next;printf("[TraverseStu]IDx:%d Name:%s\n",temp->IDx,temp->Name);}return (0);
}int FindAndDelete(STUDENT_INFO_DEF *head,STUDENT_INFO_DEF stu)
{STUDENT_INFO_DEF * temp = head;STUDENT_INFO_DEF * temp1 = NULL;if(head == NULL){printf("head NULL\n");return -1;}while(temp->Next!=NULL){temp = temp->Next;if(temp->IDx == stu.IDx) break;}temp1 = temp->Next;temp->Next = NULL;while(temp1!=NULL){free(temp1);temp1 = temp1->Next;}printf("[FindAndDelete]\n");return 0;
}int main()
{int i;/*创建链表头*/STUDENT_INFO_DEF *head; STUDENT_INFO_DEF stu;head=creat();for(i=0;i<5;i++){stu.IDx = i+1;snprintf(stu.Name, strlen("student")+2, "student%d", i+1);InsertStu(head,stu);}TraverseStu(head);stu.IDx = 2;FindAndDelete(head,stu);TraverseStu(head);getchar();return 0;
}
代码输出
weiqifa@bsp-ubuntu1804:~/c/mianshi$ gcc lianbiao.c && ./a.out
[InsertStu] IDx:1 Name:student1 Ok
[InsertStu] IDx:2 Name:student2 Ok
[InsertStu] IDx:3 Name:student3 Ok
[InsertStu] IDx:4 Name:student4 Ok
[InsertStu] IDx:5 Name:student5 Ok
[TraverseStu]IDx:1 Name:student1
[TraverseStu]IDx:2 Name:student2
[TraverseStu]IDx:3 Name:student3
[TraverseStu]IDx:4 Name:student4
[TraverseStu]IDx:5 Name:student5
[FindAndDelete]
[TraverseStu]IDx:1 Name:student1
[TraverseStu]IDx:2 Name:student2
推荐阅读:
专辑|Linux文章汇总
专辑|程序人生
专辑|C语言
我的知识小密圈