当前位置:  编程技术>c/c++/嵌入式
本页文章导读:
    ▪流言终结者——C语言内存管理       写在前头: 我不能保证此文中,我的观点和理解全是对的,这也不是一篇教学贴,只是我偶尔突发奇想了几个特殊的场景,然后用实验得到结果,对结果进行分析,遂成此文。所以文中肯定.........
    ▪MFC下托盘图标的实现和托盘菜单      对话框头文件XXXDlg.h:1.添加成员变量NOTIFYICONDATA m_nid;2.添加tray消息响应函数的声明afx_msg LRESULT OnTrayNotify(WPARAM wParam, LPARAM lParam);对话框实现文件XXXDlg.cpp:1.定义tray消息 #define UM_TRAYNOTIFY WM_USER + 112.........
    ▪C语言实现的简单通讯录例子      本程序主要利用C语言中链表和文件的相关知识,实现了能够增删改查操作的简易通讯录程序。根目录下的ctt文件是存放通讯录信息的文件,可以直接用文本编辑器打开。但是不要改动固定的.........

[1]流言终结者——C语言内存管理
    来源:    发布时间: 2013-10-17

写在前头:
我不能保证此文中,我的观点和理解全是对的,这也不是一篇教学贴,只是我偶尔突发奇想了几个特殊的场景,然后用实验得到结果,对结果进行分析,遂成此文。所以文中肯定存在错误,我也没想到会上首页,引来众人围观。
最后,欢迎拍砖,我觉得错了不要紧,改就是了,最惨的是不知道自己错在哪。

首先看一下man手册中的定义,

void *malloc(size_t size);
向系统申请size个Bytes长的连续内存,返回一个void类型的指针,指向这块儿内存的首地址。这块申请到的内存是不洁的(也就是非全0x00,内容可以是任意的,随机的)
如果size的值是0,那么返回的指针要么是指向NULL,要么是指向一个unique的地址,这个地址是可以被free释放的。(这里的解释是有问题的,例子(8)会证明)

void free(void *ptr);
释放ptr指向的内存空间,ptr必须是之前调用过malloc,calloc,realloc这三个函数返回的,否则,如果free(ptr)已经执行过了,而又执行一次,那么会导致意外发生(undefined behavior occurs.),如果ptr指向的是NULL,则不会做任何操作。

(1)假设有

1char *p = NULL;
2p = (char*)malloc(0);

那么p获得的内存块的长度到底是多少?能否往里面写入数据?
答:不妨用这段代码来测试:

01int main(int argc, char **argv)
02{
03    char *value = NULL;   
04    char *ori   = NULL;
05    value = malloc(0);
06    ori   = value;
07    printf("value[0] is [%c]\n", *value);
08    while(1) {
09        *value = 'a';
10        value++;
11        printf("value len [%d]\n", strlen(ori));
12    }
13}

这段代码结果如下所示:Fedora14:

01[michael@localhost mem-test]$ ./a.out    
02value[0] is []
03yydebug:[./mem-test.c]:[34]:value len [1]
04yydebug:[./mem-test.c]:[34]:value len [2]
05yydebug:[./mem-test.c]:[34]:value len [3]
06...(省略N行)
07yydebug:[./mem-test.c]:[34]:value len [135157]
08yydebug:[./mem-test.c]:[34]:value len [135158]
09yydebug:[./mem-test.c]:[34]:value len [135159]
10Segmentation fault (core dumped)
11[michael@localhost mem-test]$

我重新编译、运行了很多次,最后打印结果都是135159;
这个结果证明了malloc(0)返回的指针指向的是一个非NULL的内存地址处,并且该处的值是0x00,并且对于该进程,不仅该处是可写的,而且之后的135159个Bytes也都是可写的,也就是属于这个进程空间。直到最后,可能写到别的进程的空间里面去了,才被内核发来段错误信号,自己结束了。

其实在写该处就已经是内存越界了,往后继续写更加是内存越界,只是刚好那么巧,该处往后的内

    
[2]MFC下托盘图标的实现和托盘菜单
    来源:    发布时间: 2013-10-17

对话框头文件XXXDlg.h:

1.添加成员变量NOTIFYICONDATA m_nid;

2.添加tray消息响应函数的声明

afx_msg LRESULT OnTrayNotify(WPARAM wParam, LPARAM lParam);

对话框实现文件XXXDlg.cpp:

1.定义tray消息 #define UM_TRAYNOTIFY WM_USER + 11

2.CXXXDlg的构造函数添加

 memset(&m_nid, 0, sizeof(m_nid)); // Initialize NOTIFYICONDATA struct  m_nid.cbSize = sizeof(m_nid);  m_nid.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE;

3.CXXXDlg的析构函数添加

 m_nid.hIcon = NULL;  Shell_NotifyIcon(NIM_DELETE, &m_nid);

4.添加消息映射:

BEGIN_MESSAGE_MAP(CMFC2Dlg, CDialog)  //...  ON_MESSAGE(UM_TRAYNOTIFY, &CMFC2Dlg::OnTrayNotify)  //... END_MESSAGE_MAP() 

5.OnInitDialog函数添加:

m_nid.hWnd = GetSafeHwnd();  m_nid.uCallbackMessage = UM_TRAYNOTIFY;

 // Set tray icon and tooltip  m_nid.hIcon = m_hIcon;

 // Set tray notification tip information  CString strToolTip = _T("托盘程序");  _tcsncpy_s(m_nid.szTip, strToolTip, strToolTip.GetLength());  Shell_NotifyIcon(NIM_ADD, &m_nid);

6.OnTrayNotify函数的实现: LRESULT CXXXDlg::OnTrayNotify(WPARAM wParam, LPARAM lParam) {  UINT uMsg = (UINT)lParam;

 switch(uMsg)  {  case WM_RBUTTONUP:   {    //右键处理   CMenu menuTray;   CPoint point;   int id;   GetCursorPos(&point);      menuTray.LoadMenu(IDR_MENU_TRAY);   id = menuTray.GetSubMenu(0)->TrackPopupMenu(TPM_RETURNCMD | TPM_LEFTALIGN|TPM_RIGHTBUTTON, point.x, point.y, this); #if 0   CString strInfo;   strInfo.Format(L"menuid %d", id);   LPCTSTR strtmp;   strtmp = strInfo.GetBuffer(0);   MessageBox(strtmp, L"test"); #endif   switch(id){    case IDR_TRAY_EXIT:     OnOK();     break;    case IDR_TRAY_RESTORE:

    //窗口前端显示     SetForegroundWindow();     ShowWindow(SW_SHOWNORMAL);     break;    default:     break;   }   break;   }  case WM_LBUTTONDBLCLK:   SetForegroundWindow();   ShowWindow(SW_SHOWNORMAL);   break;  default:   break;  }  return 0; }

7.添加WM_SIZE消息处理:

void CMFC2Dlg::OnSize(UINT nType, int cx, int cy) {  CDialog::OnSize(nType, cx, cy);

 if(nType == SIZE_MINIMIZED){   ShowWindow(SW_HIDE);  } } 8.菜单。

添加菜单资源 , 比如IDR_MENU_TRAY.

定义一个子菜单Tray,有若干个菜单项,比如“恢复窗口”, ID是IDR_TRAY_RESTORE,“退出”, ID是IDR_TRAY_EXIT。

在OnTrayNotify函数中捕获右击消息,弹出菜单,参考第6步。

 

至此,添加托盘的功能基本完成。

本文链接


    
[3]C语言实现的简单通讯录例子
    来源:    发布时间: 2013-10-17

本程序主要利用C语言中链表和文件的相关知识,实现了能够增删改查操作的简易通讯录程序。根目录下的ctt文件是存放通讯录信息的文件,可以直接用文本编辑器打开。但是不要改动固定的格式。代码中,多处出现重复的条件判断,导致代码重复。不过,有机会的话会进行修改。

部分代码如下:

/**
* @Desc:这是一个实现通讯录的C源代码
* @Author:乌鸟
* @Version:0.1
* @URL:http://huxuemail.web-104.com
* @QQ交流群:235173087(欢迎加入)
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

//这里定义的是联合体中字符数组的长度。
#define C_NAME_SIZE 10
#define C_SEX_SIZE 3
#define C_AGE_SIZE 5
#define C_PHONE_SIZE 12
#define C_QQ_SIZE 12
#define C_PROVINCE_SIZE 20
#define C_CITY_SIZE 20
#define C_COMMENT_SIZE 100

//亲,很明显,这是函数说明!
void insRecord();//插入一条记录的实现
void inputs(char *prompt,char *info,int count);//插入一条记录时,逐行输入信息的实现
struct addr *linkNode(struct addr *i,struct addr *top);//输入完一条记录后,将当前的缓冲节点连接到链表中的实现
struct addr *find(char *name);//查找出指定的节点的实现
void seaRecord();//查找记录的实现
void delRecord();//删除记录的实现
int selectMenu();//主菜单的实现
void disRecord(addr *info);//显示一条记录的实现
void disRecords();//显示全部记录的实现
void getInfo(); //根据ctt文本中的记录,逐条返回数据项,并实现将信息插入链表,即程序启动的初始化状态的实现
void initInputs(char *initInfo[]);//输入完一条记录后,将当前的缓冲节点连接到链表中的实现
void saveRecords();//将链表中的信息全部写到磁盘文件中的实现
void saveToFile(addr *info);//将每条信息记录放到新建的文件中的实现
void editRecord();//修改记录的实现
void about();//显示作者信息的实现


//全局的东东

//联合体
struct addr
{
char c_name[C_NAME_SIZE];
char c_sex[C_SEX_SIZE];
char c_age[C_AGE_SIZE];
char c_phone[20];
char c_qq[C_QQ_SIZE];
char c_province[C_PROVINCE_SIZE];
char c_city[C_CITY_SIZE];
char c_comment[C_COMMENT_SIZE];

struct addr *next;//pointer to next entry ^^
};

//全局指针变量,info存储当前缓冲的节点、start和last存储最后一个节点、head存储头节点
struct addr *info,*start,*last,*head;
//初始化用,与head有关的变量
static int n = 0;

源代码下载地址

本文链接


    
最新技术文章:
▪C++单例模式应用实例
▪C++设计模式之迭代器模式
▪C++实现动态分配const对象实例
▪C++设计模式之中介者模式
▪C++设计模式之备忘录模式
▪C++插入排序算法实例
▪C++冒泡排序算法实例
▪C++选择排序算法实例
▪C++归并排序算法实例
▪C++设计模式之观察者模式
▪C++中复制构造函数和重载赋值操作符总结
▪C++设计模式之状态模式
▪C++设计模式之策略模式
▪C++设计模式之访问者模式
▪C++设计模式之模板方法模式
▪C++实现下载的代码
▪C++模板之特化与偏特化详解
▪C++实现查壳程序代码实例
▪C语言、C++内存对齐问题详解
▪C语言、C++中的union用法总结
▪C++基于CreateToolhelp32Snapshot获取系统进程实例
▪C++中memcpy和memmove的区别总结
▪C++通过TerminateProess结束进程实例
▪C++内存查找实例
▪C++实现CreatThread函数主线程与工作线程交互的...
▪C++设计模式之桥接模式
▪C++中关键字Struct和Class的区别
▪C++设计模式之组合模式
▪C++ COM编程之什么是组件?
▪C++ COM编程之什么是接口?
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3