首页 > 代码库 > 9.20 windows静态库和动态库的使用 函数可变参 递归使用 多线程查找

9.20 windows静态库和动态库的使用 函数可变参 递归使用 多线程查找

指针内存面试题:                          

对整个数组取地址+1前进了整个数组。再强转成double*  根据double*步长再减去1
  1. #include <stdio.h>
  2. int main()
  3. {
  4. double db[5] = {1.0,2.0,3.0,4.0,5.0};
  5. printf("%f\n", *((double *)(&db + 1) - 1)); // 结果输出5.0
  6. return 0;
  7. }

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main()
  4. {
  5. int *p = (int *)malloc(0); //内存分配0,也会分配成功。不过会发生内存冲突
  6. printf("%p\n", p);
  7. return 0;
  8. }


静态库的使用:                                  

导出静态库my.lib
  1. int sub(int a, int b)
  2. {
  3. return a - b;
  4. }

windows下使用静态库的两种方法:
1.项目设置

2.在代码里设置

#pragma comment(lib,"array.lib")       //注意此处没有分号

  1. #include <stdio.h>
  2. #pragma comment(lib,"my.lib")
  3. int main()
  4. {
  5. printf("%d\n", sub(13, 7)); //6
  6. return 0;
  7. }



动态库的使用:                                

动态库的函数必须要导出
  1. //导出函数,可以加载的时候调用
  2. _declspec(dllexport) int add(int a, int b)
  3. {
  4. return a + b;
  5. }

动态库的使用:

#include <windows.h>   //使用动态库加载需要使用windows.h头文件
  1. #include <stdio.h>
  2. #include <windows.h>
  3. typedef int(*padd)(int a, int n);//定义函数指针
  4. int main()
  5. {
  6. HMODULE mydll = LoadLibraryA("my.dll");//装载模块
  7. if (mydll == NULL)
  8. {
  9. printf("装载模块失败\n");
  10. }
  11. else
  12. {
  13. padd myadd = (padd)GetProcAddress(mydll, "add");
  14. printf("%d\n", myadd(5, 8));
  15. }
  16. FreeLibrary(mydll);//卸载模块
  17. return 0;
  18. }
可以通过VS2013的调试 -->模块窗口查看。


函数的可变参数:                             

#include <stdarg.h>           //函数可变参数的头文件
  1. #include <stdio.h>
  2. #include <stdarg.h>
  3. int add(int n, ...)
  4. {
  5. int res = 0;
  6. va_list va;
  7. va_start(va, n);
  8. for (int i = 0; i < n; i++)
  9. {
  10. res += va_arg(va, int);
  11. }
  12. va_end(va);
  13. return res;
  14. }
  15. int main()
  16. {
  17. printf("%d\n", add(3, 1, 2, 3)); //6
  18. return 0;
  19. }

通过可变参数传递字符串:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdarg.h>
  4. void runcmd(int n, ...)
  5. {
  6. va_list va;
  7. va_start(va, n);
  8. for (int i = 0; i < n; i++)
  9. {
  10. char *p = va_arg(va,char *);
  11. system(p);
  12. }
  13. va_end(va);
  14. }
  15. int main()
  16. {
  17. runcmd(3,"calc","notepad","write");//函数 依次打开 计算器 记事本 写字板
  18. return 0;
  19. }


system函数的同步与异步:   

只有关闭一个才能打开下一个notepad,阻塞模式
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main()
  4. {
  5. for (int i = 0; i < 10;i++)
  6. {
  7. system("notepad");
  8. }
  9. return 0;
  10. }

只要在system里增加了start就可以变成同步模式:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main()
  4. {
  5. for (int i = 0; i < 10;i++)
  6. {
  7. system("start notepad");
  8. }
  9. return 0;
  10. }

函数参数的副本机制:          

函数参数都具有副本机制,即使在函数里改变形参,也不会改变实参。(数组例外,数组名会退化为指针)


PS:
结构体传参也有副本机制,即使里面有数组。结构体赋值本质就是内存的拷贝。
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. struct STU
  4. {
  5. int n;
  6. int a[5];
  7. };
  8. void change(struct STU s)
  9. {
  10. s.n = 6;
  11. s.a[0] = 100;
  12. printf("%d,%d\n", s.n, s.a[0]); // 6 , 100
  13. }
  14. int main()
  15. {
  16. struct STU stu = { 5, {1,2,3,4,5} };
  17. printf("%d,%d\n", stu.n, stu.a[0]); // 5 , 1
  18. change(stu);
  19. printf("%d,%d\n", stu.n, stu.a[0]); // 5 , 1
  20. return 0;
  21. }

递归的使用场景:                   

倒序打印一个字符串:
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. void show(char *s)
  4. {
  5. if (*s == ‘\0‘)
  6. {
  7. return;
  8. }
  9. else
  10. {
  11. show(s+1);
  12. putchar(*s);
  13. }
  14. }
  15. int main()
  16. {
  17. char buf[50];
  18. scanf("%s",&buf);
  19. show(buf);
  20. return 0;
  21. }
逆序一个字符串:
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. void str_re(char *s, int n)
  4. {
  5. if (n <= 1)
  6. {
  7. return;
  8. }
  9. else
  10. {
  11. char tmp = *s;
  12. *s = s[n - 1];
  13. s[n - 1] = tmp;
  14. str_re(s + 1, n - 2);
  15. }
  16. }
  17. int main()
  18. {
  19. char buf[50] = { 0 };
  20. scanf("%s", &buf);
  21. printf("%s\n", buf);
  22. str_re(buf, strlen(buf));
  23. printf("%s\n", buf);
  24. return 0;
  25. }

递归求两个数的最大公约数:
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. int yue(int a, int b)
  4. {
  5. if (a%b == 0)
  6. return b;
  7. else
  8. return yue(b, a%b);
  9. }
  10. int main()
  11. {
  12. int a, b;
  13. scanf("%d %d", &a, &b);
  14. if (a > b)
  15. printf("%d\n", yue(a, b));
  16. else
  17. printf("%d\n", yue(b, a));
  18. return 0;
  19. }

递归 判断一个数组是否是递增:(逻辑递归)
  1. #include <stdio.h>
  2. int is_dizeng(int *a, int n)
  3. {
  4. if (n <= 1)
  5. return 1;
  6. else
  7. return a[0] < a[1] && is_dizeng(a + 1, n - 1);
  8. }
  9. int main()
  10. {
  11. int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
  12. if (is_dizeng(a, 10))
  13. {
  14. printf("是递增\n");
  15. }
  16. else
  17. {
  18. printf("不是递增\n");
  19. }
  20. return 0;
  21. }
自己写的另外一种方式
  1. int is_dizeng(int *a, int n)
  2. {
  3. if (n <= 1)
  4. return 1;
  5. else
  6. return a[n - 1] > a[n - 2] && is_dizeng(a, n - 1);
  7. }


多线程查找                                         

循环让cmd窗口打印时间:
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <windows.h>
  4. int main()
  5. {
  6. int i = 1;
  7. while (1)
  8. {
  9. char str[30] = { 0 };
  10. sprintf(str, "title 当前时间 %d 秒", i++);
  11. system(str);
  12. Sleep(1000);
  13. }
  14. return 0;
  15. }



多线程的同步和异步实现:         

下面是异步的实现方式:
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <process.h>//多线程
  5. #include <windows.h>
  6. void time(void *p)
  7. {
  8. int i = 0;
  9. while (1)
  10. {
  11. char str[100] = { 0 };
  12. sprintf(str, "title 当前时间%d秒", i);
  13. i++;
  14. system(str);//执行指令
  15. Sleep(1000);
  16. }
  17. }
  18. void gogo(void *p)
  19. {
  20. int id = *(int *)p;
  21. for (int i = 1;; i++)
  22. {
  23. if (i > 2)
  24. {
  25. printf("\n%d ,%d号线程结束", i, id);
  26. break;
  27. }
  28. Sleep(1000);
  29. }
  30. _endthread();//退出线程
  31. }
  32. void main()
  33. {
  34. _beginthread(time, 0, NULL);//先执行窗口时间
  35. int a[5] = { 1, 2, 3, 4, 5 };
  36. for (int i = 0; i < 5; i++)
  37. _beginthread(gogo, 0, &a[i]);//异步
  38. getchar();
  39. }



同步实现只需要WaitForSingleObject
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <process.h>//多线程
  5. #include <windows.h>
  6. void time(void *p)
  7. {
  8. int i = 0;
  9. while (1)
  10. {
  11. char str[100] = { 0 };
  12. sprintf(str, "title 当前时间%d秒", i);
  13. i++;
  14. system(str);//执行指令
  15. Sleep(1000);
  16. }
  17. }
  18. void gogo(void *p)
  19. {
  20. int id = *(int *)p;
  21. for (int i = 1;; i++)
  22. {
  23. if (i > 2)
  24. {
  25. printf("\n%d ,%d号线程结束", i, id);
  26. break;
  27. }
  28. Sleep(1000);
  29. }
  30. _endthread();//退出线程
  31. }
  32. void main()
  33. {
  34. _beginthread(time, 0, NULL);//先执行窗口时间
  35. int a[5] = { 1, 2, 3, 4, 5 };
  36. for (int i = 0; i < 5; i++)
  37. {
  38. HANDLE hd = _beginthread(gogo, 0, &a[i]);
  39. WaitForSingleObject(hd, INFINITE);//同步
  40. }
  41. getchar();
  42. }




多线程查找数组元素:                        
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <process.h>
  5. int flag = 0;//0为没有找到,1为找到
  6. struct MyStruct
  7. {
  8. int *pfindfirst;//查找的首地址
  9. int length;//查找的长度
  10. int num;//要查找的数据
  11. int id;//线程的编号
  12. int * pfind;//找到的地址
  13. };
  14. void find(void *p)
  15. {
  16. struct MyStruct *pstruct = p;//指针类型转换
  17. //遍历内存
  18. for (int *px = pstruct->pfindfirst; px < pstruct->pfindfirst + pstruct->length; px++)
  19. {
  20. if (flag == 1)
  21. {
  22. printf("线程%d没有找到,其他线程已经找到\n", pstruct->id);
  23. return;
  24. }
  25. if (*px == pstruct->num)//对比是否相等
  26. {
  27. pstruct->pfind = px;//赋值
  28. printf("%d号线程找到%d,%p\n", pstruct->id, *px, px);//找到提示
  29. flag = 1;
  30. return;//返回
  31. }
  32. }
  33. printf("线程%d没有找到\n", pstruct->id);
  34. }
  35. void main()
  36. {
  37. int a[1000] = { 0 };//多线程顺序查找
  38. for (int i = 0; i < 1000; i++)
  39. {
  40. a[i] = i;//赋值初始化数组
  41. }
  42. int threadnum;
  43. int findnum;
  44. printf("请输入需要多少个线程\n");
  45. scanf("%d", &threadnum);
  46. printf("请输入要查找的数据\n");
  47. scanf("%d", &findnum);
  48. //动态开辟结构体数组
  49. if (1000 % threadnum != 0)
  50. {
  51. struct MyStruct *pstruct = malloc(sizeof(struct MyStruct)*threadnum);
  52. for (int i = 0; i < threadnum - 1; i++)
  53. {
  54. pstruct[i].pfindfirst = a + i * (1000 / (threadnum - 1));//确定查找的地址
  55. pstruct[i].length = (1000 / (threadnum - 1));//查找的长度
  56. pstruct[i].id = i;//编号
  57. pstruct[i].num = findnum;//查找的数据
  58. pstruct[i].pfind = NULL;
  59. _beginthread(find, 0, &pstruct[i]);
  60. }
  61. {
  62. int i = threadnum - 1;//处理最后一个线程
  63. pstruct[i].pfindfirst = a + (1000 / (threadnum - 1))*(threadnum - 1);//确定查找的地址
  64. pstruct[i].length = 1000 - (1000 / (threadnum - 1))*(threadnum - 1);//查找的长度
  65. pstruct[i].id = i;//编号
  66. pstruct[i].num = findnum;//查找的数据
  67. pstruct[i].pfind = NULL;
  68. _beginthread(find, 0, &pstruct[i]);
  69. }
  70. }
  71. system("pause");
  72. }



来自为知笔记(Wiz)


9.20 windows静态库和动态库的使用 函数可变参 递归使用 多线程查找