windows静态库和动态库的使用 函数可变参 递归使用 多线程查找
指针内存面试题:
对整个数组取地址+1前进了整个数组。再强转成double* 根据double*步长再减去1
#include <stdio.h>
int main()
{
double db[5] = {1.0,2.0,3.0,4.0,5.0};
printf("%f\n", *((double *)(&db + 1) - 1)); // 结果输出5.0
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *p = (int *)malloc(0); //内存分配0,也会分配成功。不过会发生内存冲突
printf("%p\n", p);
return 0;
}
静态库的使用:
导出静态库my.lib
int sub(int a, int b)
{
return a - b;
}
windows下使用静态库的两种方法:
1.项目设置
2.在代码里设置
#pragma comment(lib,"array.lib") //注意此处没有分号
#include <stdio.h>
#pragma comment(lib,"my.lib")
int main()
{
printf("%d\n", sub(13, 7)); //6
return 0;
}
动态库的使用:
动态库的函数必须要导出
//导出函数,可以加载的时候调用
_declspec(dllexport) int add(int a, int b)
{
return a + b;
}
动态库的使用:
#include <windows.h> //使用动态库加载需要使用windows.h头文件
#include <stdio.h>
#include <windows.h>
typedef int(*padd)(int a, int n);//定义函数指针
int main()
{
HMODULE mydll = LoadLibraryA("my.dll");//装载模块
if (mydll == NULL)
{
printf("装载模块失败\n");
}
else
{
padd myadd = (padd)GetProcAddress(mydll, "add");
printf("%d\n", myadd(5, 8));
}
FreeLibrary(mydll);//卸载模块
return 0;
}
可以通过VS2013的调试 -->模块窗口查看。
函数的可变参数:
#include <stdarg.h> //函数可变参数的头文件
#include <stdio.h>
#include <stdarg.h>
int add(int n, ...)
{
int res = 0;
va_list va;
va_start(va, n);
for (int i = 0; i < n; i++)
{
res += va_arg(va, int);
}
va_end(va);
return res;
}
int main()
{
printf("%d\n", add(3, 1, 2, 3)); //6
return 0;
}
通过可变参数传递字符串:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
void runcmd(int n, ...)
{
va_list va;
va_start(va, n);
for (int i = 0; i < n; i++)
{
char *p = va_arg(va,char *);
system(p);
}
va_end(va);
}
int main()
{
runcmd(3,"calc","notepad","write");//函数 依次打开 计算器 记事本 写字板
return 0;
}
system函数的同步与异步:
只有关闭一个才能打开下一个notepad,阻塞模式
#include <stdio.h>
#include <stdlib.h>
int main()
{
for (int i = 0; i < 10;i++)
{
system("notepad");
}
return 0;
}
只要在system里增加了start就可以变成同步模式:
#include <stdio.h>
#include <stdlib.h>
int main()
{
for (int i = 0; i < 10;i++)
{
system("start notepad");
}
return 0;
}
函数参数的副本机制:
函数参数都具有副本机制,即使在函数里改变形参,也不会改变实参。(数组例外,数组名会退化为指针)
PS:
结构体传参也有副本机制,即使里面有数组。结构体赋值本质就是内存的拷贝。
#include <stdio.h>
#include <stdlib.h>
struct STU
{
int n;
int a[5];
};
void change(struct STU s)
{
s.n = 6;
s.a[0] = 100;
printf("%d,%d\n", s.n, s.a[0]); // 6 , 100
}
int main()
{
struct STU stu = { 5, {1,2,3,4,5} };
printf("%d,%d\n", stu.n, stu.a[0]); // 5 , 1
change(stu);
printf("%d,%d\n", stu.n, stu.a[0]); // 5 , 1
return 0;
}
递归的使用场景:
倒序打印一个字符串:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void show(char *s)
{
if (*s == '\0')
{
return;
}
else
{
show(s+1);
putchar(*s);
}
}
int main()
{
char buf[50];
scanf("%s",&buf);
show(buf);
return 0;
}
逆序一个字符串:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void str_re(char *s, int n)
{
if (n <= 1)
{
return;
}
else
{
char tmp = *s;
*s = s[n - 1];
s[n - 1] = tmp;
str_re(s + 1, n - 2);
}
}
int main()
{
char buf[50] = { 0 };
scanf("%s", &buf);
printf("%s\n", buf);
str_re(buf, strlen(buf));
printf("%s\n", buf);
return 0;
}
递归求两个数的最大公约数:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int yue(int a, int b)
{
if (a%b == 0)
return b;
else
return yue(b, a%b);
}
int main()
{
int a, b;
scanf("%d %d", &a, &b);
if (a > b)
printf("%d\n", yue(a, b));
else
printf("%d\n", yue(b, a));
return 0;
}
递归 判断一个数组是否是递增:(逻辑递归)
#include <stdio.h>
int is_dizeng(int *a, int n)
{
if (n <= 1)
return 1;
else
return a[0] < a[1] && is_dizeng(a + 1, n - 1);
}
int main()
{
int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
if (is_dizeng(a, 10))
{
printf("是递增\n");
}
else
{
printf("不是递增\n");
}
return 0;
}
自己写的另外一种方式
int is_dizeng(int *a, int n)
{
if (n <= 1)
return 1;
else
return a[n - 1] > a[n - 2] && is_dizeng(a, n - 1);
}
多线程查找
循环让cmd窗口打印时间:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <windows.h>
int main()
{
int i = 1;
while (1)
{
char str[30] = { 0 };
sprintf(str, "title 当前时间 %d 秒", i++);
system(str);
Sleep(1000);
}
return 0;
}
多线程的同步和异步实现:
下面是异步的实现方式:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <process.h>//多线程
#include <windows.h>
void time(void *p)
{
int i = 0;
while (1)
{
char str[100] = { 0 };
sprintf(str, "title 当前时间%d秒", i);
i++;
system(str);//执行指令
Sleep(1000);
}
}
void gogo(void *p)
{
int id = *(int *)p;
for (int i = 1;; i++)
{
if (i > 2)
{
printf("\n%d ,%d号线程结束", i, id);
break;
}
Sleep(1000);
}
_endthread();//退出线程
}
void main()
{
_beginthread(time, 0, NULL);//先执行窗口时间
int a[5] = { 1, 2, 3, 4, 5 };
for (int i = 0; i < 5; i++)
_beginthread(gogo, 0, &a[i]);//异步
getchar();
}
同步实现只需要WaitForSingleObject
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <process.h>//多线程
#include <windows.h>
void time(void *p)
{
int i = 0;
while (1)
{
char str[100] = { 0 };
sprintf(str, "title 当前时间%d秒", i);
i++;
system(str);//执行指令
Sleep(1000);
}
}
void gogo(void *p)
{
int id = *(int *)p;
for (int i = 1;; i++)
{
if (i > 2)
{
printf("\n%d ,%d号线程结束", i, id);
break;
}
Sleep(1000);
}
_endthread();//退出线程
}
void main()
{
_beginthread(time, 0, NULL);//先执行窗口时间
int a[5] = { 1, 2, 3, 4, 5 };
for (int i = 0; i < 5; i++)
{
HANDLE hd = _beginthread(gogo, 0, &a[i]);
WaitForSingleObject(hd, INFINITE);//同步
}
getchar();
}
多线程查找数组元素:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
int flag = 0;//0为没有找到,1为找到
struct MyStruct
{
int *pfindfirst;//查找的首地址
int length;//查找的长度
int num;//要查找的数据
int id;//线程的编号
int * pfind;//找到的地址
};
void find(void *p)
{
struct MyStruct *pstruct = p;//指针类型转换
//遍历内存
for (int *px = pstruct->pfindfirst; px < pstruct->pfindfirst + pstruct->length; px++)
{
if (flag == 1)
{
printf("线程%d没有找到,其他线程已经找到\n", pstruct->id);
return;
}
if (*px == pstruct->num)//对比是否相等
{
pstruct->pfind = px;//赋值
printf("%d号线程找到%d,%p\n", pstruct->id, *px, px);//找到提示
flag = 1;
return;//返回
}
}
printf("线程%d没有找到\n", pstruct->id);
}
void main()
{
int a[1000] = { 0 };//多线程顺序查找
for (int i = 0; i < 1000; i++)
{
a[i] = i;//赋值初始化数组
}
int threadnum;
int findnum;
printf("请输入需要多少个线程\n");
scanf("%d", &threadnum);
printf("请输入要查找的数据\n");
scanf("%d", &findnum);
//动态开辟结构体数组
if (1000 % threadnum != 0)
{
struct MyStruct *pstruct = malloc(sizeof(struct MyStruct)*threadnum);
for (int i = 0; i < threadnum - 1; i++)
{
pstruct[i].pfindfirst = a + i * (1000 / (threadnum - 1));//确定查找的地址
pstruct[i].length = (1000 / (threadnum - 1));//查找的长度
pstruct[i].id = i;//编号
pstruct[i].num = findnum;//查找的数据
pstruct[i].pfind = NULL;
_beginthread(find, 0, &pstruct[i]);
}
{
int i = threadnum - 1;//处理最后一个线程
pstruct[i].pfindfirst = a + (1000 / (threadnum - 1))*(threadnum - 1);//确定查找的地址
pstruct[i].length = 1000 - (1000 / (threadnum - 1))*(threadnum - 1);//查找的长度
pstruct[i].id = i;//编号
pstruct[i].num = findnum;//查找的数据
pstruct[i].pfind = NULL;
_beginthread(find, 0, &pstruct[i]);
}
}
system("pause");
}