金美

来源:一年级 发布时间:2020-08-21 点击:

  void GetMemory(char *p)

 {

 p = (char *)malloc(100);

 }

 void Test(void)

 {

 char *str = NULL;

 GetMemory(str);

 strcpy(str, "hello world");

 printf(str);

 }

 请问运行Test函数会有什么样的结果?

 答:程序崩溃。

 因为GetMemory并不能传递动态内存,

 Test函数中的 str一直都是 NULL。

 strcpy(str, "hello world");将使程序崩溃。

 void GetMemory2(char **p, int num)

 {

 *p = (char *)malloc(num);

 }

 void Test(void)

 {

 char *str = NULL;

 GetMemory(&str, 100);

 strcpy(str, "hello");

 printf(str);

 }

 请问运行Test函数会有什么样的结果?

 答:

 (1)能够输出hello

 (2)内存泄漏

 void foo(void)

  {

  unsigned int a = 6;

  int b = -20;

  (a+b > 6) puts("> 6") : puts("<= 6");

  }

  这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得极少这些东西。不管如何,这无符号整型问题的答案是输出是“>6”。

  原因是 当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。这 一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。如果你答错了这个问题,你也就到了得不到这份工作的边缘。

 下面是关于sizeof和strlen的说明

 第一个是char *s=“Hello”;

 Sizeof()= 4 strlen=5

 第2个是个char (*a)void()=“hello”函数指针

 第3个是个数组a【】=“hello”

 都是求sizeof=6和strlen=5

 编程题

 第一个是字符串转整形

 int my_atoi(char *s)

 {

  int i=0;

  int result=0;

  int flag=1;

  while ((*s>='0')&&(*s<='9')||(*s=='-')||(*s !='\0'))

  {

  if (*s=='-')

  {

  flag = 0;

  }

  else if ((*s>='0')&&(*s<='9'))

  {

  result=10*result+(*s-'0');

  }

  s++;

  }

  if (flag==0)

  {

  return -result;

  }

  else

  {

  return result;

  }

 }

 第2个把飞鸽好好看看考的是TCP变成和多线程

 第3个是怎么在程序中只运行一个实例(百度一下);

 /magictong/article/details/3603015

 综述:让一个程序只运行一个实例的方法有多种,但是原理都类似,也就是在程序创建前,有窗口的程序在窗口创建前,检查系统中是否已经设置了某些特定标志了,如果有说明已经有一个实例在运行了,则当前程序通知用户怎样怎样,然后程序退出,当然方法有这么多,各自也就有自己的优缺点了。<注意下面的程序都是分块拷贝的>

 方法一:

 我用得做多的方法是创建互斥体Mutex,使用Mutex代码比较简洁,但是此时不能取得已经启动的实例窗口局柄,因此无法激活已经启动的实例窗口,代码如下:

 // -------------------------------------------------------------------------

 // 函数 : CreateSendingWNDList

 // 功能 : 创建互斥量,用于保证只启动一个进程

 // 返回值 : int

 // 成功 0

 // 失败 -1

 // 存在进程实例 1

 // 附注 :

 // -------------------------------------------------------------------------

 int CreateSendingWNDList(const TCHAR *pstrKSCoreAppName)

 {

  //-------防止多次起动----------

  HANDLE hMutex = ::CreateMutex(0, true, pstrKSCoreAppName);

  int nRet = 0;

  if (hMutex)

  {

  if(GetLastError() == ERROR_ALREADY_EXISTS)

  {

  nRet = 1;

  }

  else

  {

  nRet = 0;

  }

  }

  else

  {

  nRet = -1;

  }

  return nRet;

 }

 // 在创建窗口前调用下面代码

 switch(CreateSendingWNDList(g_strKSCoreAppName))

 {

 case 0:

  // 正常启动

  // TODO……

  break;

 case 1:

  // 已存在进程,退出

  {

  ::MessageBox(NULL, TEXT("已经有一个实例在运行了。"), TEXT("注意"), MB_OK);

  }

 case -1:// 无法创建,退出

 default:

  return FALSE;

 }

 方法二:

 一般来说,使程序只运行一个实例的最简单的方法当然是使用FindWindow()查找主窗口,如果主窗口已经存在了,当然说明已经有一个实例运行了。代码如下:

 // 这种方法有缺陷,窗口名字改变之后就再也找不到了,FindWindow()的参数ClassName和Caption比较难取得。

 HWND hWnd = FindWindow(NULL, TEXT("SingleInstanceFW"));

 if(IsWindow(hWnd))

 {

  ::MessageBox(NULL, TEXT("已经有一个实例在运行了。"), TEXT("注意"), MB_OK);

  ::ShowWindow(hWnd, SW_NORMAL); // 显示

  ::SetForegroundWindow(hWnd); // 激活

  return FALSE;

 }

 方法三:

 这种方法相比上面两种方法,避免上面两种方法的缺点,通过SetProp()为程序主窗口设置一个特殊的Property,然后在启动时遍历所有的窗口,找出包含着个Property的窗口局柄

 。【这个附加的窗口属性在窗口销毁时也应该销毁】这个方法的缺点就是代码比较多一点,如下:

 // 声明全局的 属性 名和 属性值

 TCHAR g_strKSCoreAppName[] = _T("AFX_KSInstall_CPP__12036F8B_8301_46e2_ADC5_A14A44A85877__");

 HANDLE g_hValue = (HANDLE)1022;

 // 定义枚举窗口回调函数

 BOOL CALLBACK EnumWndProc(HWND hwnd, LPARAM lParam)

 {

  //TCHAR str[200] = {0};

  //::GetWindowText(hwnd, str, 200);

  HANDLE h = GetProp(hwnd, g_strKSCoreAppName);

  if(h == g_hValue)

  {

  *(HWND*)lParam = hwnd;

  return FALSE;

  }

  return TRUE;

 }

 // 主窗口创建前判断

 HWND oldHWnd = NULL;

 ::EnumWindows(EnumWndProc,(LPARAM)&oldHWnd); //枚举所有运行的窗口

 if (oldHWnd != NULL)

 {

  ::MessageBox(NULL, TEXT("已经有一个实例在运行了。"), TEXT("注意"), MB_OK);

  ::ShowWindow(oldHWnd, SW_NORMAL); // 显示

  ::SetForegroundWindow(oldHWnd); // 激活

  return FALSE;

 }

 // 主窗口创建后设置,为窗口附加一个属性

 ::SetProp(m_hWnd, g_strKSCoreAppName, g_hValue);

 // 主窗口退出时移除该附加属性

 ::RemoveProp(m_hWnd, g_strKSCoreAppName);

 方法四:

 上面的方法二和方法三都有一个弊病,不知道大家发现没,那就是依赖于窗口的存在,没有窗口的程序怎么办了,用方法一是可以的,不过方法一不太适合即时修改状态,譬如我想提供选项给用户,可以即时修改是否允许多实例,像KMP就提供了即时修改是否允许多实例,使用全局变量是一个比较好的解决方案,使用全局共享变量的方法则主要是在VC框架程序中通过编译器来实现的。通过#pragma data_seg预编译指令创建一个新节,在此节中可用volatile关键字定义一个变量,而且必须对其进行初始化。Volatile关键字指定了变量可以为外部进程访问。最后,为了使该变量能够在进程互斥过程中发挥作用,还要将其设置为共享变量,同时允许具有读、写访问权限。这可以通过#pragma comment预编译指令来通知编译器。下面给出使用了全局变量的进程互斥代码清单:

 #pragma data_seg("Shared")

 int volatile g_lAppInstance = 0;

 #pragma data_seg()

 #pragma comment(linker,"/section:Shared,RWS")

 if (0 == g_lAppInstance)

 {

  g_lAppInstance = 1;

 }

 else if (1 == g_lAppInstance)

 {

  ::MessageBox(NULL, TEXT("已经有一个实例在运行了。"), TEXT("注意"), MB_OK);

  return FALSE;

 }

 else

 {

  // 直接启动

 }

推荐访问:金韩美
上一篇:党委书记党风廉政党课讲稿2020汇总
下一篇:Wechat Business演讲稿

Copyright @ 2013 - 2018 优秀啊教育网 All Rights Reserved

优秀啊教育网 版权所有