指针初始化为NULL的作用

关于空指针NULL、野指针、通用指针,首先说一下什么是指针,只要明白了指针的含义,你就明白null的含义了。

假设 有语句 int a=10;
那么编译器就在内存中开辟1个整型单元存放变量a,我们假设这个整型单元在内存中的地址是 0x1000;那么内存0x1000单元中存放了数据10,每次我们访问a的时候,实际上都是访问的0x1000单元中的10.
现在定义:int *p;
                 p=&a;
当编译器遇到语句int *p时,它也会在内存中给指针变量p分配一个内存单元,假设这个单元在内存的编址为0x1003;此时,0x1003中的值是不确定的,(因为我们没有给指针赋值),当编译器遇到了p=&a时,就会在0x1003单元中保存0x1000,请看,这就是说:(指针变量p代表的)内存单元0x1003存放了变量a的内存地址!用通俗的话说就是p指向了变量a。
p=NULL,就是说:内存单元0x1003不存放任何变量的内存地址。

删除一个new了的数组。有必要的话。比如非标准的类( new CMyClass),在Type *p = new Type[N]; delete []p;的最后最好再加一句:   p = NULL

空指针是一个特殊的指针值,也是唯一一个对任何指针类型都合法的指针值。指针变量具有空指针值,表示它当时处于闲置状态,没有指向有意义的东西。空指针用0表示,C语言保证这个值不会是任何对象的地址。给指针值赋零则使它不再指向任何有意义的东西。为了提高程序的可读性,标准库定义了一个与0等价的符号常量NULL.    程序里可以写 p = 0;     或者 p = NULL; 两种写法都把p置为空指针值。相对而言,前一种写法更容易使读程序的人意识到这里是一个指针赋值。

我们印象中C语言的指针都有类型,实际上也存在一种例外。这里涉及到通用指针,它可以指向任何类型的变量。通用指针的类型用(void *)表示,因此也称为void 指针。
int n=3, *p;
void *gp;
gp = &n;
p=(int *)gp1;

野指针,也就是指向不可用内存区域的指针。通常对这种指针进行操作的话,将会使程序发生不可预知的错误。 
“野指针”不是NULL指针,是指向“垃圾”内存的指针。人们一般不会错用NULL指针,因为用if语句很容易判断。但是“野指针”是很危险的,if语句对它不起作用。野指针的成因主要有两种:

一、指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。

二、指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。别看free和delete的名字恶狠狠的(尤其是delete),它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。通常会用语句if (p != NULL)进行防错处理。很遗憾,此时if语句起不到防错作用,因为即便p不是NULL指针,它也不指向合法的内存块。例:

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

strcpy(p, “hello”);

free(p); // p 所指的内存被释放,但是p所指的地址仍然不变

if(p != NULL) // 没有起到防错作用

strcpy(p, “world”); // 出错

另外一个要注意的问题:不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释放。
指针是个很强大的工具,可是正因为它太强大,所以要操作它不是件易事。操作不当造成的野指针,甚至会引起系统死机等比较严重的后果。  如果程序定义了一个指针,就必须要立即让它指向一个我们设定的空间或者把它设为NULL,如果没有这么做,那么这个指针里的内容是不可预知的,即不知道它指向内存中的哪个空间(即野指针),它有可能指向的是一个空白的内存区域,可能指向的是已经受保护的区域,甚至可能指向系统的关键内存,如果是那样就糟了,也许我们后面不小心对指针进行操作就有可能让系统出现紊乱,死机了。所以我们必须设定一个空间让指针指向它,或者把指针设为NULL,这是怎么样的一个原理呢,如果是建立一个与指针相同类型的空间,实际上是在内存中的空白区域中开辟了这么一个受保护的内存空间,然后用指针来指向它,那么指针里的地址就是这个受保护空间的地址了,而不是不可预知的啦,然后我们就可以通过指针对这个空间进行相应的操作了;如果我们把指针设为NULL,我们在头文件定义中的 #define NULL 0 可以知道,其实NULL就是表示0,那么我们让指针=NULL,实际上就是让指针=0,如此,指针里的地址(机器数)就被初始化为0了,而内存中地址为0 的内存空间……不用多说也能想象吧,这个地址是特定的,那么也就不是不可预知的在内存中乱指一气的野指针了。   还应该注意的是,free和delete只是把指针所指的内存给释放掉,但并没有把指针本身干掉。指针p被free以后其地址仍然不变(非NULL),只是该地址对应的内存是垃圾,p成了“野指针”。如果此时不把p设置为NULL,会让人误以为p是个合法的指针。用free或delete释放了内存之后,就应立即将指针设置为NULL,防止产生“野指针”。内存被释放了,并不表示指针会消亡或者成了NULL指针。(而且,指针消亡了,也并不表示它所指的内存会被自动释放。)   最后,总结一下野指针的的成因吧: 1、指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的默认值是随机的,它会乱指一气。 2、指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。 3、指针操作超越了变量的作用范围。这种情况让人防不胜防。

  • 9
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
用于图片处理,包括打开,存储,移动等,。 //====================================================================== // 文件: Dib.cpp // 内容: 设备无关位图类-源文件 // 功能: (1)位图的加载与保存; // (2)位图信息的获取; // (3)位图数据的获取; // (3)位图的显示; // (4)位图的转换; // (5)位图相关判断; //====================================================================== #include "StdAfx.h" #include "Dib.h" //======================================================= // 函数功能: 构造函数,初始化数据成员 // 输入参数: 无 // 返回值: 无 //======================================================= CDib::CDib(void) { // 数据成员初始化 strcpy(m_fileName, ""); m_lpBmpFileHeader = NULL; m_lpDib = NULL; m_lpBmpInfo = NULL; m_lpBmpInfoHeader = NULL; m_lpRgbQuad = NULL; m_lpData = NULL; m_hPalette = NULL; m_bHasRgbQuad = FALSE; m_bValid = FALSE; m_rgbsum=0; } //======================================================= // 函数功能: 析构函数,释放内存空间 // 输入参数: 无 // 返回值: 无 //======================================================= CDib::~CDib(void) { // 清理空间 Empty(); } //======================================================= // 函数功能: 从文件加载位图 // 输入参数: LPCTSTR lpszPath-待加载位图文件路径 // 返回值: BOOL-TRUE 成功;FALSE 失败 //======================================================= BOOL CDib::LoadFromFile(LPCTSTR lpszPath) { // 记录位图文件名 strcpy(m_fileName, lpszPath); // 以读模式打开位图文件 CFile dibFile; if(!dibFile.Open(m_fileName, CFile::modeRead | CFile::shareDenyWrite)) { return FALSE; } // 清理空间 Empty(FALSE); // 为位图文件头分配空间,并初始化为0 m_lpBmpFileHeader = (LPBITMAPFILEHEADER)new BYTE[sizeof(BITMAPFILEHEADER)]; memset(m_lpBmpFileHeader, 0, sizeof(BITMAPFILEHEADER)); // 读取位图文件头 int nCount = dibFile.Read((void *)m_lpBmpFileHeader, sizeof(BITMAPFILEHEADER)); if(nCount != sizeof(BITMAPFILEHEADER)) { return FALSE; } // 判断此文件是不是位图文件(“0x4d42”代表“BM”) if(m_lpBmpFileHeader->bfType == 0x4d42) { // 是位图文件 //AfxMessageBox("m_lpBmpFileHeader->bfType == 0x4d42"); // 计算除位图文件头的空间大小,分配空间并初始化为0 DWORD dwDibSize = dibFile.GetLength() - sizeof(BITMAPFILEHEADER); m_lpDib = new BYTE[dwDibSize]; //(LPBYTE) new BYTE[lHeight*lineBytes24] //m_lpOldDib = new BYTE[dwDibSize]; memset(m_lpDib, 0, dwDibSize); //memset(m_lpOldDib, 0, dwDibSize); // 读取除位图文件头的所有数据 dibFile.Read(m_lpDib, dwDibSize); //dibFile.Read(m_lpOldDib, dwDibSize); // 关闭位图文件 dibFile.Close(); // 设置位图信息指针 m_lpBmpInfo = (LPBITMAPINFO)m_lpDib; // 设置位图信息头指针 m_lpBmpInfoHeader = (LPBITMAPINFOHEADER)m_lpDib; // 设置位图颜色表指针 m_lpRgbQuad = (LPRGBQUAD)(m_lpDib + m_lpBmpInfoHeader->biSize); // 如果位图没有设置位图使用的颜色数,设置它 if(m_lpBmpInfoHeader->biClrUsed == 0) { m_lpBmpInfoHeader->biClrUsed = GetNumOfColor(); //AfxMessageBox("24位"); //CString strColor; //strColor.Format("m_lpBmpInfoHeader->biClrUsed :%d",m_lpBmpInfoHeader->biClrUsed); //AfxMessageBox(strColor); } // 计算颜色表长度 DWORD dwRgbQuadLength = CalcRgbQuadLength(); //m_lpBmpInfoHeader->biPlanes = 1; //CString strColor; //strColor.Format("m_lpBmpInfoHeader->biCompression :%d", m_lpBmpInfoHeader->biPlanes); //AfxMessageBox(strColor); // 设置位图数据指针 //m_lpData = m_lpDib + m_lpBmpInfoHeader->biSize + dwRgbQuadLength; m_lpData = m_lpDib + m_lpBmpInfoHeader->biSize + dwRgbQuadLength; //m_lpOldData= m_lpOldDib + ((LPBITMAPINFOHEADER)m_lpOldDib)->biSize + dwRgbQuadLength; // 判断是否有颜色表 if(m_lpRgbQuad == (LPRGBQUAD)m_lpData) { m_lpRgbQuad = NULL; // 将位图颜色表指针置空 m_bHasRgbQuad = FALSE; // 无颜色表 //AfxMessageBox("无颜色表"); } else { m_bHasRgbQuad = TRUE; // 有颜色表 MakePalette(); // 根据颜色表生成调色板 //AfxMessageBox("加载生成调色板"); } // 设置位图大小(因为很多位图文件都不设置此项) m_lpBmpInfoHeader->biSizeImage = GetSize(); // 位图有效 m_bValid = TRUE; return TRUE; } else { // 不是位图文件 AfxMessageBox("该图不是位图!"); m_bValid = FALSE; return FALSE; } } //======================================================= // 函数功能: 将位图保存到文件 // 输入参数: LPCTSTR lpszPath-位图文件保存路径 // 返回值: BOOL-TRUE 成功;FALSE 失败 //======================================================= /*BOOL CDib::SaveToFile(LPCTSTR lpszPath) { // 以写模式打开文件 HDC hdc,hdcMem; HBITMAP hBitMap = NULL; CBitmap *pBitMap = NULL; CDC *pMemDC = NULL; BYTE *pBits; hdc = CreateIC(TEXT("DISPLAY"),NULL,NULL,NULL); hdcMem = CreateCompatibleDC(hdc); hBitMap = CreateDIBSection(hdcMem,m_lpBmpInfo,DIB_PAL_COLORS,(void **)&pBits,NULL,0); pBitMap = new CBitmap; pBitMap->Attach(hBitMap); pMemDC = new CDC; pMemDC->Attach(hdcMem); pMemDC->SelectObject(pBitMap); pMemDC->SetBkMode(TRANSPARENT); //pMemDC->SetBkMode(OPAQUE); //添加自绘图形 m_myview->DrawLine(pMemDC); CFile dibFile; if(!dibFile.Open(lpszPath, CFile::modeCreate | CFile::modeReadWrite | CFile::shareExclusive)) { return FALSE; } // 记录位图文件名 strcpy(m_fileName, lpszPath); // 将文件头结构写进文件 dibFile.Write(m_lpBmpFileHeader, sizeof(BITMAPFILEHEADER)); // 将文件信息头结构写进文件 dibFile.Write(m_lpBmpInfoHeader, sizeof(BITMAPINFOHEADER)); // 计算颜色表长度 DWORD dwRgbQuadlength = CalcRgbQuadLength(); // 如果有颜色表的话,将颜色表写进文件 if(dwRgbQuadlength != 0) { dibFile.Write(m_lpRgbQuad, dwRgbQuadlength); } // 将位图数据写进文件 DWORD dwDataSize = GetLineByte() * GetHeight(); dibFile.Write(m_lpData, dwDataSize); // 关闭文件 dibFile.Close(); return TRUE; } */ //======================================================= // 函数功能: 获取位图文件名 // 输入参数: 无 // 返回值: LPCTSTR-位图文件名 //======================================================= LPCTSTR CDib::GetFileName() { return m_fileName; } //======================================================= // 函数功能: 获取位图宽度 // 输入参数: 无 // 返回值: LONG-位图宽度 //======================================================= LONG CDib::GetWidth() { return m_lpBmpInfoHeader->biWidth; } //======================================================= // 函数功能: 获取位图高度 // 输入参数: 无 // 返回值: LONG-位图高度 //======================================================= LONG CDib::GetHeight() { return m_lpBmpInfoHeader->biHeight; } //======================================================= // 函数功能: 获取位图的宽度和高度 // 输入参数: 无 // 返回值: CSize-位图的宽度和高度 //======================================================= CSize CDib::GetDimension() { return CSize(GetWidth(), GetHeight()); } //======================================================= // 函数功能: 获取位图大小 // 输入参数: 无 // 返回值: DWORD-位图大小 //======================================================= DWORD CDib::GetSize() { if(m_lpBmpInfoHeader->biSizeImage != 0) { return m_lpBmpInfoHeader->biSizeImage; } else { return GetWidth() * GetHeight(); } } //======================================================= // 函数功能: 获取单个像素所占位数 // 输入参数: 无 // 返回值: WORD-单个像素所占位数 //======================================================= WORD CDib::GetBitCount() { return m_lpBmpInfoHeader->biBitCount; } //======================================================= // 函数功能: 获取每行像素所占字节数 // 输入参数: 无 // 返回值: UINT-每行像素所占字节数 //======================================================= UINT CDib::GetLineByte() { return (GetWidth() * GetBitCount() /8 + 3) / 4 * 4; } //======================================================= // 函数功能: 获取位图颜色数 // 输入参数: 无 // 返回值: DWORD-位图颜色数 //======================================================= DWORD CDib::GetNumOfColor() { UINT dwNumOfColor; if ((m_lpBmpInfoHeader->biClrUsed == 0) && (m_lpBmpInfoHeader->biBitCount < 9)) { switch (m_lpBmpInfoHeader->biBitCount) { case 1: dwNumOfColor = 2; break; case 4: dwNumOfColor = 16; break; case 8: dwNumOfColor = 256; } } else { dwNumOfColor = m_lpBmpInfoHeader->biClrUsed; //CString strColor; //strColor.Format("dwNumOfColor:%d",dwNumOfColor); //AfxMessageBox(strColor); } return dwNumOfColor; } //======================================================= // 函数功能: 计算位图颜色表长度 // 输入参数: 无 // 返回值: DWORD-位图颜色表长度 //======================================================= DWORD CDib::CalcRgbQuadLength() { DWORD dwNumOfColor = GetNumOfColor(); if(dwNumOfColor > 256) { dwNumOfColor = 0; } CString strColor; strColor.Format("dwNumOfColor:%d",dwNumOfColor); //AfxMessageBox(strColor); return dwNumOfColor * sizeof(RGBQUAD); } //======================================================= // 函数功能: 计算位图像素的起始位置 // 输入参数: 无 // 返回值: LPBYTE-位图像素的起始位置 //======================================================= LPBYTE CDib::GetBits() { return (m_lpDib+((LPBITMAPINFOHEADER)m_lpDib)->biSize+CalcRgbQuadLength()); } //======================================================= // 函数功能: 获取位图颜色表 // 输入参数: 无 // 返回值: LPRGBQUAD-位图颜色表指针 //======================================================= LPRGBQUAD CDib::GetRgbQuad() { return m_lpRgbQuad; } //======================================================= // 函数功能: 获取位图数据 // 输入参数: 无 // 返回值: LPBYTE-位图数据指针 //======================================================= LPBYTE CDib::GetData() { return m_lpData; } //======================================================= // 函数功能: 根据颜色表生成调色板 // 输入参数: 无 // 返回值: BOOL-TRUE 成功;FALSE 失败 //======================================================= BOOL CDib::MakePalette() { // 计算颜色表长度 DWORD dwRgbQuadLength = CalcRgbQuadLength(); CString strColor; strColor.Format("dwRgbQuadLength:%d",dwRgbQuadLength); //AfxMessageBox(strColor); // 如果颜色表长度为0,则不生成逻辑调色板 if(dwRgbQuadLength == 0) { return FALSE; } //删除旧的调色板对象 if(m_hPalette != NULL) { DeleteObject(m_hPalette); m_hPalette = NULL; } // 申请缓冲区,初始化为0 DWORD dwNumOfColor = GetNumOfColor(); DWORD dwSize = 2 * sizeof(WORD) + dwNumOfColor * sizeof(PALETTEENTRY); LPLOGPALETTE lpLogPalette = (LPLOGPALETTE) new BYTE[dwSize]; memset(lpLogPalette, 0, dwSize); // 生成逻辑调色板 lpLogPalette->palVersion = 0x300; lpLogPalette->palNumEntries = dwNumOfColor; LPRGBQUAD lpRgbQuad = (LPRGBQUAD) m_lpRgbQuad; for(int i = 0; i < dwNumOfColor; i++) { lpLogPalette->palPalEntry[i].peRed = lpRgbQuad->rgbRed; lpLogPalette->palPalEntry[i].peGreen = lpRgbQuad->rgbGreen; lpLogPalette->palPalEntry[i].peBlue = lpRgbQuad->rgbBlue; lpLogPalette->palPalEntry[i].peFlags = 0; lpRgbQuad++; } // 创建逻辑调色板 m_hPalette = CreatePalette(lpLogPalette); // 释放缓冲区 delete [] lpLogPalette; return TRUE; } //======================================================= // 函数功能: 显示位图 // 输入参数: // CDC *pDC-设备环境指针 // CPoint origin-显示矩形区域的左上角 // CSize size-显示矩形区域的尺寸 // 返回值: // BOOL-TRUE 成功;FALSE 失败 //======================================================= BOOL CDib::Draw(CDC *pDC, CPoint origin, CSize size) { // 位图无效,无法绘制,返回错误 if(!IsValid()) { return FALSE; } // 旧的调色板句柄 HPALETTE hOldPalette = NULL; // 如果位图指针为空,则返回FALSE if(m_lpDib == NULL) { return FALSE; } // 如果位图有调色板,则选进设备环境中 if(m_hPalette != NULL) { hOldPalette = SelectPalette(pDC->GetSafeHdc(), m_hPalette, TRUE); } // 设置位图伸缩模式 pDC->SetStretchBltMode(COLORONCOLOR); // 将位图在pDC所指向的设备上进行显示 StretchDIBits(pDC->GetSafeHdc(), origin.x, origin.y, size.cx, size.cy, 0, 0, GetWidth(), GetHeight(), m_lpData, m_lpBmpInfo, DIB_RGB_COLORS, SRCCOPY); // 恢复旧的调色板 if(hOldPalette != NULL) { SelectPalette(pDC->GetSafeHdc(), hOldPalette, TRUE); } return TRUE; } //======================================================= // 函数功能: 24位彩色位图转8位灰度位图 // 输入参数: 无 // 返回值: BOOL-TRUE 成功;FALSE 失败 //======================================================= BOOL CDib::RgbToGrade() { // 位图无效,失败返回 if(!IsValid()) { AfxMessageBox("该位图无效!"); return FALSE; } // 是压缩位图,失败返回 if(m_lpBmpInfoHeader->biCompression != BI_RGB) { return FALSE; } // 如果不是灰度位图,才需要转换 if(!IsGrade()) { // 获取原位图信息 LONG lHeight = GetHeight(); LONG lWidth = GetWidth(); UINT uLineByte = GetLineByte(); // 计算灰度位图数据所需空间 UINT uGradeBmpLineByte = (lWidth * 8 / 8 + 3) / 4 * 4; DWORD dwGradeBmpDataSize = uGradeBmpLineByte * lHeight; // 计算灰度位图所需空间 DWORD dwGradeBmpSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256 + dwGradeBmpDataSize; // 设置灰度位图文件头 LPBITMAPFILEHEADER lpGradeBmpFileHeader = (LPBITMAPFILEHEADER)new BYTE[sizeof(BITMAPFILEHEADER)]; memset(lpGradeBmpFileHeader, 0, sizeof(BITMAPFILEHEADER)); lpGradeBmpFileHeader->bfType = 0x4d42; lpGradeBmpFileHeader->bfSize = sizeof(BITMAPFILEHEADER) + dwGradeBmpSize; lpGradeBmpFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256; lpGradeBmpFileHeader->bfReserved1 = 0; lpGradeBmpFileHeader->bfReserved2 = 0; // 为灰度位图分配空间,并初始化为0 LPBYTE lpGradeBmp = (LPBYTE)new BYTE[dwGradeBmpSize]; memset(lpGradeBmp, 0, dwGradeBmpSize); // 设置灰度位图信息头 LPBITMAPINFOHEADER lpGradeBmpInfoHeader = (LPBITMAPINFOHEADER)(lpGradeBmp); lpGradeBmpInfoHeader->biBitCount = 8; lpGradeBmpInfoHeader->biClrImportant = 0; lpGradeBmpInfoHeader->biClrUsed = 256; lpGradeBmpInfoHeader->biCompression = BI_RGB; lpGradeBmpInfoHeader->biHeight = lHeight; lpGradeBmpInfoHeader->biPlanes = 1; lpGradeBmpInfoHeader->biSize = sizeof(BITMAPINFOHEADER); lpGradeBmpInfoHeader->biSizeImage = dwGradeBmpDataSize; lpGradeBmpInfoHeader->biWidth = lWidth; lpGradeBmpInfoHeader->biXPelsPerMeter = m_lpBmpInfoHeader->biXPelsPerMeter; lpGradeBmpInfoHeader->biYPelsPerMeter = m_lpBmpInfoHeader->biYPelsPerMeter; // 设置灰度位图颜色表 LPRGBQUAD lpGradeBmpRgbQuad = (LPRGBQUAD)(lpGradeBmp + sizeof(BITMAPINFOHEADER)); // 初始化8位灰度图的调色板信息 LPRGBQUAD lpRgbQuad; for(int k = 0; k < 256; k++) { lpRgbQuad = (LPRGBQUAD)(lpGradeBmpRgbQuad + k); lpRgbQuad->rgbBlue = k; lpRgbQuad->rgbGreen = k; lpRgbQuad->rgbRed = k; lpRgbQuad->rgbReserved = 0; } // 灰度位图数据处理 BYTE r, g, b; LPBYTE lpGradeBmpData = (LPBYTE)(lpGradeBmp + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256); // 进行颜色转换 for(int i = 0; i < lHeight; i++) { for(int j = 0; j < lWidth; j++) { b = m_lpData[i * uLineByte + 3 * j]; g = m_lpData[i * uLineByte + 3 * j + 1]; r = m_lpData[i * uLineByte + 3 * j + 2]; lpGradeBmpData[i * uGradeBmpLineByte + j] = (BYTE)(0.299 * r + 0.587 * g + 0.114 * b); } } // 释放原有位图空间 Empty(FALSE); // 重新设定原位图指针指向 m_lpBmpFileHeader = lpGradeBmpFileHeader; m_lpDib = lpGradeBmp; m_lpBmpInfo = (LPBITMAPINFO)(lpGradeBmp); m_lpBmpInfoHeader = lpGradeBmpInfoHeader; m_lpRgbQuad = lpGradeBmpRgbQuad; m_lpData = lpGradeBmpData; // 设置颜色表标志 m_bHasRgbQuad = TRUE; // 设置位图有效标志 m_bValid = TRUE; // 生成调色板 MakePalette(); } AfxMessageBox("转换成功,请保存8位灰度图!"); return TRUE; } //======================================================= // 函数功能: 8位彩色位图转24位彩色图 // 输入参数: 无 // 返回值: BOOL-TRUE 成功;FALSE 失败 //======================================================= BOOL CDib::GraphToRgb() { // 位图无效,失败返回 if(!IsValid()) { AfxMessageBox("该位图无效!"); return FALSE; } // 是压缩位图,失败返回 if(m_lpBmpInfoHeader->biCompression != BI_RGB) { return FALSE; } if(GetBitCount()==24) { AfxMessageBox("该位图已是24位,不用转换!"); return FALSE; } if(GetBitCount()!=8) { AfxMessageBox("该位图不是8位,不能转换,请用画图软件将其另存为成24位图!"); return FALSE; } // 如果不是24位图,才需要转换 // 获取原位图信息 LONG lHeight = GetHeight(); LONG lWidth = GetWidth(); UINT uLineByte = GetLineByte(); // 计算24位图数据所需空间 //return (GetWidth() * GetBitCount() /8 + 3) / 4 * 4; UINT uGradeBmpLineByte = (lWidth * 24/8 + 3) / 4 * 4; DWORD dwGradeBmpDataSize = uGradeBmpLineByte * lHeight; // 计算24位图所需空间 DWORD dwGradeBmpSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 0 + dwGradeBmpDataSize; // 设置24位图文件头 LPBITMAPFILEHEADER lpGradeBmpFileHeader = (LPBITMAPFILEHEADER)new BYTE[sizeof(BITMAPFILEHEADER)]; memset(lpGradeBmpFileHeader, 0, sizeof(BITMAPFILEHEADER)); lpGradeBmpFileHeader->bfType = 0x4d42; lpGradeBmpFileHeader->bfSize = sizeof(BITMAPFILEHEADER) + dwGradeBmpSize; lpGradeBmpFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); lpGradeBmpFileHeader->bfReserved1 = 0; lpGradeBmpFileHeader->bfReserved2 = 0; // 为24位图分配空间,并初始化为0 LPBYTE lpGradeBmp = (LPBYTE)new BYTE[dwGradeBmpSize]; memset(lpGradeBmp, 0, dwGradeBmpSize); // 设置24位图信息头 LPBITMAPINFOHEADER lpGradeBmpInfoHeader = (LPBITMAPINFOHEADER)(lpGradeBmp); lpGradeBmpInfoHeader->biBitCount = 24; lpGradeBmpInfoHeader->biClrImportant = 0; lpGradeBmpInfoHeader->biClrUsed = 0; lpGradeBmpInfoHeader->biCompression = BI_RGB; lpGradeBmpInfoHeader->biHeight = lHeight; lpGradeBmpInfoHeader->biPlanes = 1; lpGradeBmpInfoHeader->biSize = sizeof(BITMAPINFOHEADER); lpGradeBmpInfoHeader->biSizeImage = dwGradeBmpDataSize; lpGradeBmpInfoHeader->biWidth = lWidth; lpGradeBmpInfoHeader->biXPelsPerMeter = 0; lpGradeBmpInfoHeader->biYPelsPerMeter = 0; // 设置24位图颜色表 //LPRGBQUAD lpGradeBmpRgbQuad = (LPRGBQUAD)(lpGradeBmp + sizeof(BITMAPINFOHEADER)); // 初始化8位灰度图的调色板信息 /*LPRGBQUAD lpRgbQuad; for(int k = 0; k < 256; k++) { lpRgbQuad = (LPRGBQUAD)(lpGradeBmpRgbQuad + k); lpRgbQuad->rgbBlue = k; lpRgbQuad->rgbGreen = k; lpRgbQuad->rgbRed = k; lpRgbQuad->rgbReserved = 0; }*/ // 24位图数据处理 //BYTE r, g, b; //LPBYTE lpGradeBmpData = (LPBYTE)(lpGradeBmp + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 0); // 进行颜色转换 LONG lineBytes24=(lWidth * 24 / 8 + 3) / 4 * 4; LONG lineBytes8=(lWidth * 8 / 8 + 3) / 4 * 4; //LONG lineBytes24=(lWidth * 24 + 31) / 32 * 4; //LONG lineBytes8=(lWidth * 8 + 31) / 32 * 4; //CString strColor; //strColor.Format("lineBytes24 :%d,lineBytes8 :%d", lineBytes24,lineBytes8); //AfxMessageBox(strColor); LPBYTE lpGradeBmpData =(LPBYTE) new BYTE[lHeight*lineBytes24]; for(int i = 0; i < lHeight; i++) { for(int j = 0,n=0; j < lineBytes8; j++,n++) { BYTE gray=*(m_lpData+lineBytes8*i+j); *(lpGradeBmpData+lineBytes24*i+n)=gray; n++; *(lpGradeBmpData+lineBytes24*i+n)=gray; n++; *(lpGradeBmpData+lineBytes24*i+n)=gray; /*lpGradeBmpData[lineBytes24*i+j ]= m_lpData[lineBytes8*i+j]; lpGradeBmpData[lineBytes24*i+j+1]= m_lpData[lineBytes8*i+j]; lpGradeBmpData[lineBytes24*i+j+2]= m_lpData[lineBytes8*i+j];*/ } } // 释放原有位图空间 //AfxMessageBox("转换成功"); Empty(FALSE); // 重新设定原位图指针指向 m_lpBmpFileHeader = lpGradeBmpFileHeader; m_lpDib = lpGradeBmp; m_lpBmpInfo = (LPBITMAPINFO)(lpGradeBmp); m_lpBmpInfoHeader = lpGradeBmpInfoHeader; //m_lpRgbQuad = lpGradeBmpRgbQuad; m_lpData = lpGradeBmpData; // 设置颜色表标志 //m_bHasRgbQuad = TRUE; // 设置位图有效标志 m_bValid = TRUE; // 生成调色板 //MakePalette(); AfxMessageBox("转换成功,请保存24位图!"); return TRUE; } //======================================================= // 函数功能: 判断是否含有颜色表 // 输入参数: 无 // 返回值: 判断结果:TRUE-含有颜色表;FALSE-不含颜色表 //======================================================= BOOL CDib::HasRgbQuad() { return m_bHasRgbQuad; } //======================================================= // 函数功能: 判断是否是灰度图 // 输入参数: 无 // 返回值: 判断结果:TRUE-是灰度图;FALSE-是彩色图 //======================================================= BOOL CDib::IsGrade() { return (GetBitCount() < 9 && GetBitCount() > 0); } //======================================================= // 函数功能: 判断位图是否有效 // 输入参数: 无 // 返回值: 判断结果:TRUE-位图有效;FALSE-位图无效 //======================================================= BOOL CDib::IsValid() { return m_bValid; } //======================================================= // 函数功能: 清理空间 // 输入参数: BOOL bFlag-TRUE 全部清空;FALSE 部分清空 // 返回值: 无 //======================================================= void CDib::Empty(BOOL bFlag) { // 文件名清空 if(bFlag) { strcpy(m_fileName, ""); } // 释放位图文件头指针空间 if(m_lpBmpFileHeader != NULL) { delete [] m_lpBmpFileHeader; m_lpBmpFileHeader = NULL; } // 释放位图指针空间 if(m_lpDib != NULL) { delete [] m_lpDib; m_lpDib = NULL; m_lpBmpInfo = NULL; m_lpBmpInfoHeader = NULL; m_lpRgbQuad = NULL; m_lpData = NULL; } // 释放调色板 if(m_hPalette != NULL) { DeleteObject(m_hPalette); m_hPalette = NULL; } // 设置不含颜色表 m_bHasRgbQuad = FALSE; // 设置位图无效 m_bValid = FALSE; } BOOL CDib::CountClr(int r,int g,int b,int fanwei) { m_rgbsum=0; // 位图无效,失败返回 if(!IsValid()) { AfxMessageBox("该位图无效!"); return FALSE; } if(GetBitCount()!=24) { CString str; str.Format("该位图是%d位,无法统计,请用画图软件将其另存为成24位图!",GetBitCount()); AfxMessageBox(str); return FALSE; } // 是压缩位图,失败返回 if(m_lpBmpInfoHeader->biCompression != BI_RGB) { return FALSE; } //LoadFromFile((LPCTSTR)m_fileName); // 获取原位图信息 LONG lHeight=GetHeight(); LONG lWidth=GetWidth(); UINT uLineByte=GetLineByte(); // 灰度位图数据处理 int R=0, G=0, B=0; //int R1=0, G1=0, B1=0; // 进行颜色转换 int clrfanwei; int clrjizhun=0.299 * r + 0.587 * g + 0.114 * b;//基准灰度 for(int i = 0; i < lHeight; i++) { for(int j = 0; j < lWidth; j++) { //(BYTE)(0.299 * r + 0.587 * g + 0.114 * b); B = *(m_lpData+i * uLineByte + 3 * j); G = *(m_lpData+i * uLineByte + 3 * j + 1); R = *(m_lpData+i * uLineByte + 3 * j + 2); int someonegray=0.299 * R + 0.587 * G + 0.114 * B; if(clrjizhun<128)//标定深色区域为缺陷 { clrfanwei=clrjizhun+fanwei; if(clrfanwei>255) clrfanwei=255; if(someonegray<=clrfanwei && someonegray>=clrjizhun) { if(r==255 && g==0 && b==0) { *(m_lpData+i * uLineByte + 3 * j)=255; *(m_lpData+i * uLineByte + 3 * j + 1)=0; *(m_lpData+i * uLineByte + 3 * j + 2)=0; } else { *(m_lpData+i * uLineByte + 3 * j)=0; *(m_lpData+i * uLineByte + 3 * j + 1)=0; *(m_lpData+i * uLineByte + 3 * j + 2)=255; } m_rgbsum++; } } else//标定浅色区域为缺陷 { clrfanwei=clrjizhun-fanwei; if(clrfanwei<0) clrfanwei=0; if(someonegray>=clrfanwei && someonegray<=clrjizhun) { if(r==255 && g==0 && b==0) { *(m_lpData+i * uLineByte + 3 * j)=255; *(m_lpData+i * uLineByte + 3 * j + 1)=0; *(m_lpData+i * uLineByte + 3 * j + 2)=0; } else { *(m_lpData+i * uLineByte + 3 * j)=0; *(m_lpData+i * uLineByte + 3 * j + 1)=0; *(m_lpData+i * uLineByte + 3 * j + 2)=255; } m_rgbsum++; } } } } return TRUE; } BOOL CDib::TranslationRight(long lXOffset,long lYOffset) { long i; long j; long lWidth,lHeight; lWidth=GetWidth(); lHeight=GetHeight(); //LPBYTE lpSrcDIBBits; long lLineBytes; lLineBytes=GetLineByte(); if (lXOffset<=0 || lYOffset<=0) { return FALSE; } for(i=0;i<lHeight;i+=(2*lYOffset)) { int index=0; do { for(j=0;j<GetWidth();j++) { if(index<lYOffset) { if((lWidth-j-lXOffset)>=0) { *(m_lpData+(i+index) * lLineBytes + 3 * (lWidth-j))=*(m_lpData+(i+index) * lLineBytes + 3 * (lWidth-j-lXOffset)); *(m_lpData+(i+index) * lLineBytes + 3 * (lWidth-j) + 1)=*(m_lpData+(i+index) * lLineBytes + 3 * (lWidth-j-lXOffset) + 1); *(m_lpData+(i+index) * lLineBytes + 3 * (lWidth-j) + 2)=*(m_lpData+(i+index)* lLineBytes + 3 * (lWidth-j-lXOffset) + 2); } else { break; } } else { if((i+index)<lHeight) { *(m_lpData+(i+index) * lLineBytes + 3 * j)=*(m_lpData+(i+index) * lLineBytes + 3 * j); *(m_lpData+(i+index) * lLineBytes + 3 * j + 1)=*(m_lpData+(i+index) * lLineBytes + 3 * j + 1); *(m_lpData+(i+index) * lLineBytes + 3 * j + 2)=*(m_lpData+(i+index) * lLineBytes + 3 * j + 2); } else { break; } } } index++; //AfxMessageBox("平移中!"); } while(index<2*lYOffset); } return TRUE; } BOOL CDib::TranslationLeft(long lXOffset,long lYOffset) { long i; long j; long lWidth,lHeight; lWidth=GetWidth(); lHeight=GetHeight(); //LPBYTE lpSrcDIBBits; long lLineBytes; lLineBytes=GetLineByte(); if (lXOffset<=0 || lYOffset<=0) { return FALSE; } for(i=0;i<lHeight;i+=(2*lYOffset)) { int index=0; do { for(j=0;j<GetWidth();j++) { if(index<lYOffset) { if((j+lXOffset)<=lWidth) { *(m_lpData+(i+index) * lLineBytes + 3 * j)=*(m_lpData+(i+index) * lLineBytes + 3 * (j+lXOffset)); *(m_lpData+(i+index) * lLineBytes + 3 * j + 1)=*(m_lpData+(i+index) * lLineBytes + 3 * (j+lXOffset) + 1); *(m_lpData+(i+index) * lLineBytes + 3 * j + 2)=*(m_lpData+(i+index)* lLineBytes + 3 * (j+lXOffset) + 2); } else { break; } } else { if((i+index)<lHeight) { *(m_lpData+(i+index) * lLineBytes + 3 * j)=*(m_lpData+(i+index) * lLineBytes + 3 * j); *(m_lpData+(i+index) * lLineBytes + 3 * j + 1)=*(m_lpData+(i+index) * lLineBytes + 3 * j + 1); *(m_lpData+(i+index) * lLineBytes + 3 * j + 2)=*(m_lpData+(i+index) * lLineBytes + 3 * j + 2); } else { break; } } } index++; //AfxMessageBox("平移中!"); } while(index<2*lYOffset); } return TRUE; }
用C语言实现的128位AES加密算法,可以运行在JAVA的JNI 中AIS加密算法c语言实现代码 nt cnt for(ent =0: cnt< 8: cnt++) BvtcToBit(*(ch+cnt), bit+(ent<<3)) return /将二进制位串转为长度为8的字符串水 int Bit64ToChar8 (ElemType bitL64, ElemType ch18) int cnt memset(ch, 0, 8) for(ent-0: cnt<8: cnt++i BitToByte(bit+(cnt<<3), ch+cnt) return 0 /*生成子密钥 int DES Make Subkeys(ElemType key _64, ElemType subkeys [16][48]) ElemType temp 56 int cnt DES PCI Transform(key,temp):/*PCI置换* for(cnt=0;cnt<16;cnt+-){*16轮跌代,产生16个子密钥米 DES ROL(tenp, MOVE TIMES[cnt]);循坏左移* DES PC2 Transform(temp, subkeys cnt]);/PC2置换,产生子密钥体 return o /*密钥置換1*/ int DES PCI Transform(ElemType key [64, ElemType tempts[56])t int cnt for(cnt=0: cnt( 56 cnt++) )empts[cnt]= key[ Ilant] r巳turn /*密钥置換2* int DES PC2 Transform(Elem Type key [56], ElemType tempts[48])i t cnt for(ent =0: cnt< 48: cnt+)I )pbts [cnt]= key [PC 2[cnt]] return /*循环左移*/ int DES ROL (Elem Type data[56], int time)t Elem l'ype temp _56 /*保存将要循环栘动到右边的位* memcpy(temp, data, time) memcpy(temg-time, data+28, time) /*前28位移动 (data-28-time, temp, time) /*后28位移动* memcpy(data 28, data+28+time, 28-time memcpy (data-56-time, temp+time, time) return o /*P置换*/ int DES IP) Iransform(Elemlype data[64)[ ElemType temp _64]: for(cnt templet- datalIP Tablelcnt」」 memcpy(data, temp, 64) return o 第3页 AIS加密算法c语言实现代码 /*IP逆置換* int DES IP 1 Transform(ElemType data[64)( int cnt ElemType temp _64 for(cnt =0: cnt 64: cnt+-)i templet」- dataLIP1 Tablelcrt]」 memcpy(data, temp, 64) return o /*扩展置换*/ int DES E Transform(ElemType data[48])( Int cn ElemType temp48」 for(ent-0: cnt 48: cnt-) temp lent= datale Tablelent memcpy( data, temp, 48 return o P置换 int DES P Transform(ElemType data[32])( t ElemType temp_32] for(ent =0; cnt 32; cnt+-) temp ent-datalP Tablel 11 me.mcpy(data, temp, 32) return 0 /水异或* int DES XOR(Elem Type R[48, Elem Type L[48], int count)I int cnt for(cnt-0: cnt< count: cnt++)i RIant]= lent] return 0 /*S盒置换*/ int DES SBOX (Elem Type data[48]) int cnt int line, row, output int curl, cur for(ent=0; cnt( 8: cnt++i curl cnt:6 cur2= cnt<<2 /*计算在S盒中的行与列来 line=(data cur1<<1)+ data[ cur1+5 row=(data[cur1+1]<<3)+(data[cur1+2]<<2) +(data「cur1-31<<1)+data「cur1+41 output s[cnt][line]trow] /*化为2进制*/ data[cur2]=(output&0X08)>>3 data[cur2+1]=(output&0X04)>>2 data (output&0X02)>1 datalcur 2+3= output&0x01 return o 交换 int DES Swap(ElemType left[32], ElemType right [32]) memcpy(temp, left, 32 memcpy(left, right, 32 memcpy (right, temp, 32 return o 第4页 AIS加密算法c语言实现代码 /*加密单个分组 int DES EncryptBlockElem Type plainBlock[8, ElemType subKeys[l6][48, ElemType cipherBlock[8])I ElemT'ype plainTs [54] ElemType copyRight[48] int cnt Char8ToBit64(plainBlock, plairBits) /米初始置换(IP置换)* DES IP Transform(plainBits /*16轮迭代* for(cnt=0: cnt< 16: cnt+-) memcpy(copyRight, plainBits- 32, 32 /*将右半部分进行扩展置换,从32位扩展到48位*/ DES E Trans form(copyRight) /*将右半部分与子密钥进行异或操作 DES XOR (copy Righ 48) /*异或结果进入S盒,输出32位结果*/ DES SBOX (copyRight) /P置换 DES P Transform(copyRight) /*将明文左半部分与右半部分进行异或* DES XOR (plainBits, copyRight, 32) 最终完成左右部的交换* DES Swap(plainBits, plainBits-32) /逆初始置换(IPI置换)* DES IP 1 Transform (plainBits) Bit64ToChar8(plainBits, cipherBlock) turn o /*解密单个分组 int DES DecryptBlock(ElemType cipherBlock[8, ElemType subKeys[16] 18], ElemType plainBlock [81) ElemType cipherBits[ 641 Elem Type copy Right [48] int cnt Char8ToBit64(cipherBlock, cipherBits) /初始置换(IP置换)* DES IP Transform(cipherBits /*16轮迭代*/ for(cnt-15: cnt >-0: cnt--)i memcpy(copyRight, cipherBits+32, 32 /*将右半部分进行扩展置换,从32位扩展到48位 DES T Trans form(copyright) /*将右半部分与子密钥进行异或操作 DES XOR(copy Right, subKeys [ent], 48) /*异或结果进入S盒,输出32位结果* DES SBOX(copyRight) /米P置换* DES P Transform(copyright) /*将明文h半部分与右半部分进行异或* DES XOR (cipherBits, copy Right, 32) f(cnt /米最终完成左右部的交换* DES Swap(cipherBits, cipherBits+32) /*逆初始置换(IP1置换)* DES IP 1 Transform(cipherBits) Bit64ToChar8(cipherBits, plainBlock) return 0: *加密文件 int DES Encrypt (char xplainFile, char *keyStr, char *cipherFile)t FILE xplain, i*cipher; int count ElcmType plainBlock[81, ciphcrBlock [8, keyBlock 8 第5页 AIS加密算法c语言实现代码 Elem Type bEy 64] ElemType subKeys[16][18] if((plain- fopen(plainFilc, " rb"))--NULL) return Plain FILe OPEN ERROR return CIPHER FILE OPEN ERROR: ))== NULL)( if ((cipher fopen(cipherFile, wb /设置密钥 memcpy (keyBlock, key Str, 8) 将密钥转换为二进制流* Char8ToBit64(keyBlock, bKcy /牛成子密钥* DES Make SubKeys(bEy, subKeys while(!feof plain))( /*每次读8个字节,并返回成功读取的字节数* if((count- fread(plainBlock, sizeof(char),8, plain)) 8){ DES EncryptBlock (plainBlock, subKeys, cipherBlock f(count)[ /*填充*/ memset(plainBlock ount, \0, 7- count) /*最后一个字符休存包括最后一个字符在内的所填充的字符数量水 plainblockl7-8-count DES EncryptBlock (plainBlock, subkeys, cipherBlock fwrite(cipherBlock, sizeof (char), 8, cipher) fclose (plain) f'c. lose(cipher return oK /*解密文件* int DES Decrypt(char *cipherFile, char *key Str, char xplainFile)i FILE* plain,米 cipher int count, times 0 long fileLen Eleml'ype plainBlock [8], cipherBlock[8], keyBlock[8 ElemType bEy _6 ElemType subKeys[16][48] if ((cipher fopen(cipherFile, rb ))= NULL)[ return CIPHEr FILe OPEN ERROR if((plain= fopen(plainFile, wb" ))= NULL) rcturn plain FIle OPEN ERROR /*设置密钥* memcpy(key Block, keyStr, 8) /将密钥转换为二进制流* Char8ToBit64 (keyBlock, bKey) /水生成子密钥* ES Make SubKeys(bKey subKeys) /取文什长度*/ fseek( cipher,0, SEEK END);/将文件指针置尾 fi lelen= ftel l( cipher);/*取文件指针当前位置*/ rewind( CIpher);/*将文件指针重指向文件头* while(1)i 密文的字节数一定是8的整数倍* fread(cipherBlock, sizeof(char), 8, cipher DES DecryptBlock(cipherBlock, subKeys, plainBlock) times +-8 if(times< fileLen fwrite(plainBlock, sizeof(char), 8, plain) /*判断末尾是否被填充米 if(plainBlock 71< 8)i 第6页 AIS加密算法c语言实现代码 for(count=8- plainBlock[7]; count< 7; count++)( if(plainBlock[ count!='\0i break if( count==7){/*有填充* fwrite(plairBlock, sizeof (char), 8- plainBlockL7, plain) else{/*无填充 fwrite(plainBlock, sizeof(char), 8, plain) t'close ( plain) fclose(cipher) return OK int main() clock t a, b a= clockO DES Encrypt( 1. txt, key. txt, 2. txt b=clock o printf("加密消耗%毫秒Ⅶn",b-a); system("pause") a= clock( DES Decrypt( 2. txt, key. txt", 3. txt") printf("解密消耗%毫秒、n",o-a) getcharo return 第7页
适合新手的教程,我自己也在学,以下是部分学习笔记 69 函数指针 70 动态内存分配 Dynamic memory pointer = new type pointer = new type [elements] 第一个表达式用来给一个单元素的数据类型分配内存。第二个表达式用来给一个数组分配内存。 例如: int * bobby; bobby = new int [5]; if (bobby == NULL) { // error assigning memory. Take measures. }; delete pointer; delete [ ] pointer; 在C语言中,为了动态分配内存,我们必须求助于函数库stdlib.h 因为该函数库在C++中仍然有效,并且在一些现存的程序仍然使用,所以我们下面将学习一些关于这个函数库中的函数用法。 函数malloc void * malloc (size_t nbytes); char * cp; cp = (char *) malloc (10); int * bobby; bobby = (int *) malloc (5 * sizeof(int)); 这一小段代码将一个指向可存储5个int型整数的内存块的指针赋给bobby,它的实际长度可能是 2,4或更多字节 数,取决于程序是在什么操作系统下被编译的。 int * bobby; bobby = (int *) calloc (5, sizeof(int)); malloc 和calloc的另一点不同在于calloc 会将所有的元素初始化为0。 它被用来改变已经被分配给一个指针的内存的长度。 void * realloc (void * pointer, size_t size); 参数pointer 用来传递一个已经被分配内存的指针或一个空指针,而参数size 用来指明新的内存长度。这个函数 给指针分配size 字节的内存。这个函数可能需要改变内存块的地址以便能够分配足够的内存来满足新的长度要 求。在这种情况下,指针当前所指的内存中的数据内容将会被拷贝到新的地址中,以保证现存数据不会丢失。函 数返回新的指针地址。如果新的内存尺寸不能够被满足,函数将会返回一个空指针,但原来参数中的指针 pointer 及其内容保持不变。 函数 free 这个函数用来释放被前面malloc, calloc 或realloc所分配的内存块。 void free (void * pointer); 注意:这个函数只能被用来释放由函数malloc, calloc 和realloc所分配的空间。 74 数据结构 76-78 结构指针(Pointers to structures) -> 这是一个引用操作符,常与结构或类的指针一起使用,以便引用其中的成员元素,这样就避免使用很多括号。例如,我们用: pmovie->title 来代替: (*pmovie).title 79 自定义数据类型(User defined data types) typedef existing_type new_type_name; typedef char C; typedef unsigned int WORD; typedef char * string_t; typedef char field [50]; 80 联合(Union) union mytypes_t { char c; int i; float f; } mytypes; 81 枚举Enumerations (enum) enum model_name { value1, value2, value3, . . } object_name; 例如,我们可以定义一种新的变量类型叫做color_t 来存储不同的颜色: enum colors_t {black, blue, green, cyan, red, purple, yellow, white}; 注意在这个定义里我们没有使用任何基本数据类型。换句话说,我们创造了一种的新的数据类型,而它并没有基 于任何已存在的数据类型:类型color_t,花括号{}中包括了它的所有的可能取值。例如,在定义了colors_t 列举 类型后,我们可以使用以下表达式: 84 类(Class) 类(class)是一种将数据和函数组织在同一个结构里的逻辑方法。定义类的关键字为class ,其功能与C语言中的struct类似,不同之处 是class可以包含函数,而不像struct只能包含数据元素。 类定义的形式是: class class_name { permission_label_1: member1; permission_label_2: member2; ... } object_name; 其中 class_name 是类的名称 (用户自定义的类型) ,而可选项object_name 是一个或几个对象(object)标识。Class的声明体中包含 成员members,成员可以是数据或函数定义,同时也可以包括允许范围标志 permission labels,范围标志可以是以下三个关键字中 任意一个:private:, public: 或 protected:。它们分别代表以下含义: ● private :class的private成员,只有同一个class的其他成员或该class的“friend” class可以访问这些成员。 ● protected :class的protected成员,只有同一个class的其他成员,或该class的“friend” class,或该class的子类(derived classes) 可以访问这些成员。 ● public :class的public成员,任何可以看到这个class的地方都可以访问这些成员。 如果我们在定义一个class成员的时候没有声明其允许范围,这些成员将被默认为 private范围。 以下是怎样读前面例子中出现的一些指针和类操作符 (*, &, ., ->, [ ]): ● *x 读作: pointed by x (由x指向的) ● &x 读作: address of x(x的地址) ● x.y 读作: member y of object x (对象x的成员y) ● (*x).y 读作: member y of object pointed by x(由x指向的对象的成员y) ● x->y 读作: member y of object pointed by x (同上一个等价) ● x[0] 读作: first object pointed by x(由x指向的第一个对象) ● x[1] 读作: second object pointed by x(由x指向的第二个对象) ● x[n] 读作: (n+1)th object pointed by x(由x指向的第n+1个对象) 由关键字struct和union定义的类 类不仅可以用关键字class来定义,也可以用struct或union来定义。 因为在C++中类和数据结构的概念太相似了,所以这两个关键字struct和class的作用几乎是一样的(也就是说在C++中struct定义的 类也可以有成员函数,而不仅仅有数据成员)。两者定义的类的唯一区别在于由class定义的类所有成员的默认访问权限为private,而 struct定义的类所有成员默认访问权限为public。除此之外,两个关键字的作用是相同的。 union的概念与struct和class定义的类不同, 因为union在同一时间只能存储一个数据成员。但是由union定义的类也是可以有成员函 数的。union定义的类访问权限默认为public。 94 操作符重载(Overloading operators) + - * / = < > += -= *= /= << >> <<= >>= == != <= >= ++ -- % & ^ ! | ~ &= ^= |= && || %= [] () new delete 96 this指针 97 静态成员(静态变量、静态函数)(Static members) 静态成员类直接访问,不属于类对象的成员 98 类之间的关系(Relationships between classes) 友元函数(Friend functions) 101 类的继承 记住,this 代表代码正在被执行的这一个对象的指针。 142 函数模块 154 出错处理 (Exception handling) 159 类型转换高级 (Advacned Class Type-casting) 163 typeid 164 预处理指令 168 标准函数库
1.介绍一下STL,详细说明STL如何实现vector。 Answer: STL (标准模版库,Standard Template Library.它由容器算法迭代器组成。 STL有以下的一些优点: 可以方便容易地实现搜索数据或对数据排序等一系列的算法; 调试程序时更加安全和方便; 即使是人们用STL在UNIX平台下写的代码你也可以很容易地理解(因为STL是跨平台的)。 vector实质上就是一个动态数组,会根据数据的增加,动态的增加数组空间。 2.如果用VC开发程序,常见这么几个错误,C2001,c2005,c2011,这些错误的原因是什么。 Answer:   在学习VC++的过程中,遇到的LNK2001错误的错误消息主要为:   unresolved external symbol “symbol”(不确定的外部“符号”)。   如果连接程序不能在所有的库和目标文件内找到所引用的函数、变量或标签,将产生此错误消息。 一般来说,发生错误的原因有两个:一是所引用的函数、变量不存在、拼写不正确或者使用错误;其次可能使用了不同版本的连接库。 编程中经常能遇到LNK2005错误——重复定义错误,其实LNK2005错误并不是一个很难解决的错误. 3.继承和委派有什么分别,在决定使用继承或者委派的时候需要考虑什么。 在OOD,OOP中,组合优于继承. 当然多态的基础是继承,没有继承多态无从谈起。 当对象的类型不影响类中函数的行为时,就要使用模板来生成这样一组类。 当对象的类型影响类中函数的行为时,就要使用继承来得到这样一组类. 4.指针和引用有什么分别;如果传引用比传指针安全,为什么?如果我使用常量指针难道不行吗? (1) 引用在创建的同时必须初始化,即引用到一个有效的对象;而指针在定义的时候不必初始化,可以在定义后面的任何地方重新赋值. (2) 不存在NULL引用,引用必须与合法的存储单元关联;而指针则可以是NULL. (3) 引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引用;而指针在任何时候都可以改变为指向另一个对象.给引用赋值并不是改变它和原始对象的绑定关系. (4) 引用的创建和销毁并不会调用类的拷贝构造函数 (5) 语言层面,引用的用法和对象一样;在二进制层面,引用一般都是通过指针来实现的,只不过编译器帮我们完成了转换. 不存在空引用,并且引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引用,显得很安全。 const 指针仍然存在空指针,并且有可能产生野指针. 总的来说:引用既具有指针的效率,又具有变量使用的方便性和直观性. 5.参数传递有几种方式;实现多态参数传递采用什么方式,如果没有使用某种方式原因是什么; 传值,传指针或者引用 6.结合一个项目说明你怎样应用设计模式的理念。 设计模式更多考虑是扩展和重用,而这两方面很多情况下,往往会被忽略。 不过,我不建议滥用设计模式,以为它有可能使得简单问题复杂化. 7.介绍一下你对设计模式的理解。(这个过程中有很多很细节的问题随机问的) 设计模式概念是由建筑设计师Christopher Alexander提出:"每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心.这样,你就能一次又一次地使用该方案而不必做重复劳动."上述定义是对设计模式的广义定义.将其应用到面向对象软件的领域内,就形成了对设计模式的狭义定义. 可以简单的认为:设计模式就是解决某个特定的面向对象软件问题的特定方法, 并且已经上升到理论程度。 框架与设计模式的区别: 1,设计模式和框架针对的问题域不同.设计模式针对面向对象的问题域;框架针对特定业务的问题域 2,设计模式比框架更为抽象.设计模式在碰到具体问题后,才能产生代码;框架已经可以用代码表示 3,设计模式是比框架更小的体系结构元素.框架中可以包括多个设计模式 设计模式就像武术中基本的招式.将这些招式合理地纵组合起来,就形成套路(框架),框架是一种半成品. 8.C++和C定义结构的分别是什么。 C language 的结构仅仅是数据的结合 C plus plus的struct 和 class 其实具备几乎一样的功能,只是默认的访问属性不一样而已。 9.构造函数可否是虚汗数,为什么?析构函数呢,可否是纯虚的呢? 构造函数不能为虚函数,要构造一个对象,必须清楚地知道要构造什么,否则无法构造一个对象。 析构函数可以为纯虚函数。 10,拷贝构造函数相关问题,深拷贝,浅拷贝,临时对象等。 深拷贝意味着拷贝了资源和指针,而浅拷贝只是拷贝了指针,没有拷贝资源 这样使得两个指针指向同一份资源,造成对同一份析构两次,程序崩溃。 临时对象的开销比局部对象小些。 11.结合1个你认为比较能体现OOP思想的项目,用UML来描述。(最好这个项目继承,多态,虚函数都有体现)这个问题大概会占面试时间的一半,并且会问很多问题,一不小心可能会被问住)。 。。。 12。基类的有1个虚函数,子类还需要申明为virtual吗?为什么。 不申明没有关系的。 不过,我总是喜欢显式申明,使得代码更加清晰。 13.C也可以通过精心封装某些函数功能实现重用,那C++的类有什么优点吗,难道仅仅是为实现重用。 并不仅仅是这样的。 OOD,OOP从根本上改变了程序设计模式和设计思想,具备重大和深远的意义。 类的三大最基本的特征:封装,继承,多态. 14.C++特点是什么,如何实现多态?画出基类和子类在内存中的相互关系。 多态的基础是继承,需要虚函数的支持,简单的多态是很简单的。 子类继承父类大部分的资源,不能继承的有构造函数,析构函数,拷贝构造函数,operator=函数,友元函数等等 15.为什么要引入抽象基类和纯虚函数? 主要目的是为了实现一种接口的效果。 16.介绍一下模板和容器。如何实现?(也许会让你当场举例实现) 模板可以说比较古老了,但是当前的泛型编程实质上就是模板编程。 它体现了一种通用和泛化的思想。 STL有7种主要容器:vector,list,deque,map,multimap,set,multiset. 17.你如何理解MVC。简单举例来说明其应用。 MVC模式是observer 模式的一个特例,典型的有MFC里面的文档视图架构。 18,多重继承如何消除向上继承的二义性。 使用虚拟继承即可.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值