1.不同的数据类型所占的字节数
16位编译器 char :1个字节char (即指针变量): 2个字节 * short int : 2个字节int: 2个字节 unsigned int : 2个字节 float: 4个字节 double: 8个字节 long: 4个字节 long long: 8个字节 unsigned long: 4个字节
32位编译器 char :1个字节char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器) short int : 2个字节int: 4个字节 unsigned int : 4个字节 float: 4个字节 double: 8个字节 long: 4个字节 long long: 8个字节 unsigned long: 4个字节
64位编译器
char :1个字节char (即指针变量): 8个字节 * short int : 2个字节int: 4个字节 unsigned int : 4个字节 float: 4个字节 double: 8个字节long: 8个字节 long long: 8个字节
unsigned long: 8个字节
2.各种声明的格式 例如:
函数声明
typedef
…….
3.数字逻辑真值表 输入A B C 输出Y
输入布尔型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 #include <stdio.h> #define NUM_INPUTS 3 #define NUM_ROWS 8 int truthTable[NUM_ROWS][NUM_INPUTS + 1 ] = { {0 , 0 , 0 , 0 }, {0 , 0 , 1 , 1 }, {0 , 1 , 0 , 0 }, {0 , 1 , 1 , 0 }, {1 , 0 , 0 , 1 }, {1 , 0 , 1 , 1 }, {1 , 1 , 0 , 0 }, {1 , 1 , 1 , 1 } }; int computeOutput (int inputs[NUM_INPUTS]) { for (int i = 0 ; i < NUM_ROWS; i++) { int match = 1 ; for (int j = 0 ; j < NUM_INPUTS; j++) { if (inputs[j] != truthTable[i][j]) { match = 0 ; break ; } } if (match) { return truthTable[i][NUM_INPUTS]; } } return -1 ; } int main () { int inputs[NUM_INPUTS] = { 1 , 0 , 1 }; int result = computeOutput(inputs); printf ("Output: %d\n" , result); return 0 ; }
4.各种排序方法 例如:冒泡排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include <stdio.h> void main () { int a[10 ] = { 4 ,2 ,8 ,6 ,5 ,7 ,3 ,9 ,1 ,0 }; for (int i = 0 ; i < 10 -1 ; i++) { for (int j = 0 ; j < 10 -1 - i ; j++) if (a[j] > a[j +1 ]) { int temp = a[j]; a[j] = a[j+1 ]; a[j+1 ] = temp; } } for (int i = 0 ; i < 10 ; i++) printf ("%d " , a[i]); }
选择排序法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include <stdio.h> void main () { int a[10 ] = { 4 ,2 ,8 ,6 ,5 ,7 ,3 ,9 ,1 ,0 }; for (int i = 0 ; i < 10 -1 ; i++) { for (int j = i + 1 ; j < 10 ; j++) if (a[i] > a[j ]) { int temp = a[i]; a[i] = a[j]; a[j] = temp; } } for (int i = 0 ; i < 10 ; i++) printf ("%d " , a[i]); }
5.程序编写 例1:
一个生产线有K台设备同时工作,用一个数组ns存储每项产品加工所需的时间,以及给出数组的长度为len
求最小总用时 和 哪几项产品给同一台设备完成
例:输入 k=3 ns[len]={4 5 7 1 3 } len=5 总共三个输入
k 代表总共有3台设备
ns[len]={4 5 7 1 3 } 代表总共有len件产品需要加工,每件产品加工所需的时间分别为 4、 5 、7 、1、 3分钟
请计算出怎么分配那些产品给那台设备加工,使得总加工时长可以最短?
输出格式:
给出任意的 k ns len ,编写C语言程序实现功能
6.C语言数据运算 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include <stdio.h> int main () { int x = 15 , y = 8 ; float z; z = x / y; printf ("z = %f\n" ,z); z = (float )(x / y); printf ("z = %f\n" , z); z = (float )x / y; printf ("z = %f\n" , z); z = x / (float )y; printf ("z = %f\n" , z); return 0 ; }
运行结果:
1 2 3 4 z = 1.000000 z = 1.000000 z = 1.875000 z = 1.875000
7.define宏定义仅仅只是单纯的替换(只做替换,不做计算) 1 2 3 4 5 6 7 8 9 10 #include <stdio.h> #define M 2 #define N M+1 int main () { printf ("M*N=%d\n" , M * N); return 0 ; }
运行结果:
8.数组首地址是一个常量指针 1 2 3 4 5 6 7 8 9 10 11 12 13 结果: A.2 B.3 C.数组名是一个数组的首地址指针,它是一个常量指针,不能被修改。
9.sizeof(运算符)和strlen(函数)的区别 文档链接:https://blog.csdn.net/qq_47908816/article/details/123964670
使用strlen函数,需要对应的头文件#include <string.h>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include <stdio.h> #include <string.h> int main () { int n = 10 ; char str[] = "hello" ; char * p = str; printf ("%d\n" ,sizeof (n)); printf ("%d\n" ,sizeof (str)); printf ("%d\n" ,strlen (str)); printf ("%d\n" ,sizeof (p)); }
输出结果:
strlen=string length,顾名思义,该函数是用来求解字符串的长度的。简单来说就是求出字符串的实际长度;
记住任何一个字符串的结尾都会隐藏一个“\0”,他是字符串的结束标志,而sizeof在计算时会添加上这一项,一般结果为字符串的实际长度+“\0”
数组的结束标志问题:
1 2 3 4 5 6 7 8 9 10 11 #include <stdio.h> #include <string.h> int main () { char arr1[] = { 'a' ,'b' ,'c' ,'d' ,'e' ,'f' }; char arr2[] = { 'a' ,'b' ,'c' ,'d' ,'e' ,'f' ,'\0' }; printf ("%d\n" , strlen (arr1)); printf ("%d\n" , strlen (arr2)); return 0 ; }
输出结果:
问题原因:对于arr1数组来说,没有在数组中额外存储”\0”,所以编译器在读取时,并不会像我们所期望的那样停止读取,故长度当然不会时6,至于为什么是38,是因为在读取时,编译器读取完arr1时会继续往后读取,直到读取到”\0”,arr1在读取完第38个字符后才会遇到”\0”;由于每个人的电脑和编译器不同,读取的长度也不一样,所以arr1这种情况一般我们认为它读取的结果为随机值!!!
sizeof:
相比strlen函数,sizeof就简单多了,sizeof其实就是一个运算符 ,主要用来计算所占空间字节的大小。
10.重新实现strcpy(char *A , const char *B)函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <stdio.h> void my_strcpy (char *A, const char *B) { while (*B) { *A = *B; A++; B++; } *A = '\0' ; } int main () { char destination[100 ]; const char source[] = "Hello, World!" ; my_strcpy(destination, source); printf ("Copied string: %s\n" , destination); return 0 ; }
11.如果a是个数组,则a和&a之间的区别 1)a和&a
a:数组名,表示数组中第一个元素的地址
&a:整个数组在内存中的起始地址
a == &a(两者对应的值是相同的,但其所代表的含义并不相同)
区别:
a:指向的的是数组中元素的地址
&a :指向的是整个数组作为一个单元的起始地址
12.大小端模式 大端模式:数据的低位放在内存高地址中,数据的高位放在内存的低地址中
小端模式:数据的高位放在内存高地址中,数据的低位放在内存的低地址中
13.C++中空类占用内存空间大小(大小为1个字节) 14.假设有a, b两个变量,在不使用第三个变量的情况下,交换a, b两个变量的值 a = a + b;
b = a - b;
a = a - b;
14.一级指针和二级指针 一级指针: int *pt; –> pt指针指向的地址里面存放的是int类型的数据
二级指针: int **pt; –> pt指针指向的地址里面存放的是一个指向整型变量的地址
15 .大疆笔试
16.CISC和RISC
17.广州众远智慧科技有限公司(笔试)
18.C语言实现以下功能 输入m和n
m代表要输入的IP个数
n代表m个IP中互相连接的组数
接下来输入m组IP地址以及每组IP地址的序号
然后输入n组两两连通的IP地址的序号
接下来输入要测试连通性的IP组数q
接下来输入q组IP地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 输入示例: 5 3 192.168 .0 .1 1 192.168 .0 .2 2 192.168 .0 .3 3 192.168 .0 .4 4 192.168 .0 .5 5 1 2 2 3 4 5 3 192.168 .0 .1 192.168 .0 .2 192.168 .0 .2 192.168 .0 .3 192.168 .0 .3 192.168 .0 .4 输出示例: YES YES NO
完整的示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 #include <stdio.h> #include <string.h> #define MAX_IP_COUNT 100 #define MAX_GROUP_COUNT 100 int main () { int m, n; scanf ("%d %d" , &m, &n); char ips[MAX_IP_COUNT][12 ]; for (int i = 0 ; i < m; i++) { scanf ("%s" , ips[i]); int sequence; scanf ("%d" , &sequence); } int groups[MAX_GROUP_COUNT][2 ]; for (int i = 0 ; i < n; i++) { scanf ("%d %d" , &groups[i][0 ], &groups[i][1 ]); } int q; scanf ("%d" , &q); for (int i = 0 ; i < q; i++) { char ip1[16 ], ip2[16 ]; scanf ("%s %s" , ip1, ip2); int ip1_index = -1 , ip2_index = -1 ; for (int j = 0 ; j < m; j++) { if (strcmp (ip1, ips[j]) == 0 ) { ip1_index = j; } if (strcmp (ip2, ips[j]) == 0 ) { ip2_index = j; } } int connected = 0 ; for (int j = 0 ; j < n; j++) { if ((groups[j][0 ] == ip1_index + 1 && groups[j][1 ] == ip2_index + 1 ) || (groups[j][0 ] == ip2_index + 1 && groups[j][1 ] == ip1_index + 1 )) { connected = 1 ; break ; } } if (connected) { printf ("YES\n" ); } else { printf ("NO\n" ); } } return 0 ; }
自己写的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 #include <stdio.h> #include <string.h> int main () { int m, n; scanf ("%d %d" ,&m,&n); char in_dex[50 ][12 ]; for (int i=0 ;i<m;i++) { scanf ("%s" ,in_dex[i]); int lins; scanf ("%d" ,&lins); } int links[20 ][2 ]; for (int i = 0 ; i < n; i++) { scanf ("%d %d" ,&links[i][0 ], &links[i][1 ]); } int x; char test_in[2 ][12 ]; scanf ("%d" ,&x); for (int i= 0 ;i<x;i++) { scanf ("%s %s" , test_in[0 ], test_in[1 ]); int index1 = -1 ; int index2 = -1 ; for (int j= 0 ;j<m;j++) { if (strcmp (in_dex[j], test_in[0 ]) == 0 ) index1 = j; if (strcmp (in_dex[j], test_in[1 ]) == 0 ) index2 = j; } int flag = 0 ; for (int i = 0 ; i < n; i++) { if ((links[i][0 ] == index1 + 1 && links[i][1 ] == index2 + 1 ) || (links[i][0 ] == index2 + 1 && links[i][1 ] == index1 + 1 )) flag = 1 ; } if (flag==1 ) printf ("YES" ); else printf ("NO" ); } return 0 ; } 10 :00 10 :40 11 :00 3 5 6 3 9 4 7 0 3 5 2 1 6 2 2 6 3 7 4 2 5 8 6 2 0 4 8 0 5 1 6 2 4 3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 #include "stdio.h" #include "string.h" int main () { int m, n; scanf ("%d" , &m); int index[10 ][2 ]; for (int i=0 ;i<m;i++) { scanf ("%d" ,&n); int num = 0 ; for (int j = 0 ; j < n;j++) { scanf ("%d %d" , &index[j][0 ], &index[j][1 ]); num = num + j + 1 ; } for (int j = 0 ; j <n; j++) { num = num - (index[j][1 ]); } int result[10 ]; for (int i = 0 ; i < n; i++) { result[i] = index[num-1 ][0 ]; num = index[num-1 ][1 ]; } for (int i = n-1 ; i >=0 ; i--) { printf ("%d " , result[i]); } } }
C语言实现字母重组功能
例 输入:
abc
输出 :
abc
acb
bca
bac
cba
cab
20.GCC的四个工作阶段 解释文档:https://blog.csdn.net/jb_home/article/details/113448528
预处理(Pre-Processing)
编译(compiling)
汇编(Assembling)
链接(Linking)
21.判断素数和回文数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 #include <stdio.h> #include <stdbool.h> bool is_prime (int num) { if (num <= 1 ) { return false ; } for (int i = 2 ; i * i <= num; i++) { if (num % i == 0 ) return false ; } return true ; } bool is_palindrome (int num) { int original = num; int reverse = 0 ; while (num > 0 ) { int digit = num % 10 ; reverse = reverse * 10 + digit; num /= 10 ; } return original == reverse; } int main () { int M; printf ("请输入大于100的整数M:" ); scanf ("%d" , &M); if (M <= 100 ) { printf ("输入的数必须大于100。\n" ); return 1 ; } printf ("100到%d之间的回文素数有:\n" , M); for (int num = 101 ; num <= M; num++) { if (is_prime(num) && is_palindrome(num)) { printf ("%d " , num); } } printf ("\n" ); return 0 ; }
22.UART、IIC、SPI UART: 全双工通信,先发送低位,再发送高位
IIC: 半双工通信,先发送低位,再发送高位,最低的一位为通信方向(0代表主机发送数据,1代表主机接收数据)
SPI: 全双工通信,先发送高位,再发送低位
23.C语言实现:假设有两个整形数组a和b,a是有序递增的,b是有序递减的。假设a中有足够的空间合并b,要求不使用额外的空间,把b合并到a后,需要去重新保证有序递增
24.C语言实现:输入一个字符串,找出其中连续数字组成的最大数并返回。假定字符串只包含字母和数字,如果数字超过int表示的最大范围,就返回-1,如果没有找到数字,就返回0
25.x=255,当x大于0时一直执行 x=x&(x-1)总共可以执行几次 8次 这个问题涉及到一个计算 x 的二进制表示中有多少个 1 的问题。具体来说,执行 x = x & (x - 1) 操作将会消除 x 二进制表示中的最低位的 1。每次执行这个操作,都会减少 x 的二进制表示中的一个 1,因此我们可以通过多次执行这个操作来计算 x 二进制表示中有多少个 1,直到 x 变为 0 为止。
26.static变量默认的初始化值是多少 0 1 2 static int x; static int * ptr;
27.void*可以转化为任何指针 void*是C语言中的通用指针类型,它可以用来存储任何数据类型的地址。因此,你可以将void*转换为任何指针类型,但需要使用显式的类型转换。
28.char是无符号类型? char 类型在C语言中可以是有符号的,也可以是无符号的,具体取决于编译器和编译器选项。
通常情况下,你可以使用signed char来明确指定有符号char,或使用unsigned char来明确指定无符号char。
29.运算符优先级 https://zhuanlan.zhihu.com/p/512384798
! > 算术运算符 > 关系运算符 > && > || > 赋值运算符
30.设已有说明语句“int a=5则执行语句: a+-=a*=a%=3的值为
首先,计算 a *= a,这相当于 a = a * a,因此 a 的值现在变为 25。
接下来,计算 a %= 3,这相当于 a = a % 3,因此 a 的值现在变为 1(25 除以 3 的余数)。
最后,计算 a += -a,这相当于 a = a + (-a),这会将 a 的值置为 1 - 1,最终 a 的值仍然是 0。
因此,执行语句 a += -a *= a %= 3 后,变量 a 的值为 0。
31.C语言实现:编写一个函数,输入是一个无符号整数,返回其二进制表达式中数字位数为“1”的个数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include <stdio.h> int countOnes (unsigned int num) { int count = 0 ; while (num != 0 ) { if (num & 1 ) { count++; } num >>= 1 ; } return count; } int main () { unsigned int num; printf ("请输入一个无符号整数:" ); scanf ("%u" , &num); int result = countOnes(num); printf ("二进制中数字位数为1的个数为:%d\n" , result); return 0 ; }
31.C语言实现:输入一个字符串,找出其中连续数字组成的最大数并返回。假定字符串只包含字母和数字,如果数字超过int表示的最大范围,就返回-1,如果没有找到数字,就返回0 例如:输入:ADD754ASD7851AD 输出:7851 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 #include <stdio.h> #include <string.h> #include <stdlib.h> long long findMaxNumber (const char * str) { long long maxNumber = 0 ; long long currentNumber = 0 ; int isNegative = 0 ; int foundNumber = 0 ; for (int i = 0 ; str[i] != '\0' ; i++) { char currentChar = str[i]; if (currentChar >= '0' && currentChar <= '9' ) { foundNumber = 1 ; currentNumber = currentNumber * 10 + (currentChar - '0' ); if (currentNumber > LLONG_MAX) { return -1 ; } } else { if (foundNumber) { if (currentNumber > maxNumber) { maxNumber = currentNumber; } currentNumber = 0 ; } } } if (foundNumber) { if (isNegative) { currentNumber = -currentNumber; } if (currentNumber > maxNumber) { maxNumber = currentNumber; } } return foundNumber ? maxNumber : 0 ; } int main () { char input[100 ]; printf ("请输入一个字符串:" ); scanf ("%s" , input); long long result = findMaxNumber(input); if (result == -1 ) { printf ("数字超过long long类型的最大范围,返回-1\n" ); } else if (result == 0 ) { printf ("没有找到数字,返回0\n" ); } else { printf ("连续数字组成的最大数为:%lld\n" , result); } return 0 ; }
32. 中断向量表中保存的是中断处理程序的入口地址
33.C语言实现求解两个整数的最大公约数 使用欧几里得算法(也称为辗转相除法)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #include <stdio.h> int gcd (int a, int b) ;int main () { int num1, num2; printf ("输入两个整数:\n" ); scanf ("%d %d" , &num1, &num2); int result = gcd(num1, num2); printf ("最大公约数是:%d\n" , result); return 0 ; } int gcd (int a, int b) { int temp; while (b != 0 ) { temp = b; b = a % b; a = temp; } return a; }
34.链表插入操作时,通常使用二级指针而不是一级指针的原因? 你有一个链表,并且要实现一个函数来在链表的头部插入一个新的节点。如果你只传递指向链表头部的指针(一级指针),那么在函数内部插入新节点后,链表的头部指针不会在函数外部发生变化 ,因为C语言中函数参数传递是按值传递的,传递的是参数的拷贝 。
但是,如果你传递指向指针的指针(二级指针),函数内部可以修改指针的值,使它指向新插入的节点。这会反映在函数外部 ,从而使链表的头部指针指向新插入的节点。
35.检测链表是否存在环 要在C语言中检测一个链表是否存在环,你可以使用快慢指针算法(Floyd’s Tortoise and Hare Algorithm)。这个算法使用两个指针,一个慢指针 (龟)每次移动一个节点,一个快指针 (兔)每次移动两个节点。如果链表中存在环,那么快指针最终会追上慢指针。如果链表没有环,快指针将会到达链表的末尾。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 #include <stdio.h> #include <stdbool.h> struct Node { int data; struct Node * next ; }; bool hasCycle (struct Node* head) { if (head == NULL || head->next == NULL ) { return false ; } struct Node * slow = head; struct Node * fast = head; while (fast != NULL && fast->next != NULL ) { slow = slow->next; fast = fast->next->next; if (slow == fast) { return true ; } } return false ; } int main () { struct Node * head = NULL ; struct Node * second = NULL ; struct Node * third = NULL ; head = (struct Node*)malloc (sizeof (struct Node)); second = (struct Node*)malloc (sizeof (struct Node)); third = (struct Node*)malloc (sizeof (struct Node)); head->data = 1 ; head->next = second; second->data = 2 ; second->next = third; third->data = 3 ; third->next = NULL ; third->next = head; bool hasCycleResult = hasCycle(head); if (hasCycleResult) { printf ("链表存在环\n" ); } else { printf ("链表不存在环\n" ); } return 0 ; }
36.函数指针的用法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 在C语言中,你可以定义一个指针,该指针指向一个函数,这个函数被称作函数指针。下面是如何定义一个指向函数的指针的示例: int my_function (int a, int b) { return a + b; } int (*my_function_ptr)(int , int );my_function_ptr = &my_function; 在这个例子中,my_function_ptr是一个指向函数的指针,该函数接受两个int 类型的参数并返回一个int 类型的结果。我们通过&my_function获取my_function的地址,并将这个地址赋值给my_function_ptr。 然后,你可以通过这个函数指针来调用函数: int result = my_function_ptr(3 , 4 ); 这样,你就可以创建一个指向特定函数的指针,并在运行时决定调用哪个函数。
37.二位数组和指针的用法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include <stdio.h> int main () { int a[][3 ] = {9 ,8 ,7 ,6 ,5 ,4 ,3 ,2 ,1 }; int * ptr = a[1 ]; printf ("%d\n" ,*ptr); printf ("%d\n" ,*(ptr+2 )); return 0 ; } 6 4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include <stdio.h> int main () { int a[][3 ] = { {9 }, {6 ,5 }, {3 ,2 ,1 } }; int * ptr = a[1 ]; printf ("%d\n" ,*ptr); printf ("%d\n" ,*(ptr+2 )); return 0 ; } 6 0