C、C++筆記

2017年6月 閱讀書籍《C和指針》ios


 #if 0windows

 #endifapi

比註釋掉代碼好。(《C和指針》2017.06.07)數組


 

全局變量和全局靜態變量的區別
1)全局變量是不顯式用static修飾的全局變量,全局變量默認是有外部連接性的,做用域是整個工程,在一個文件內定義的全局變量,在另外一個文件中,經過extern 全局變量名的聲明,就可使用全局變量。
2)全局靜態變量是顯式用static修飾的全局變量,做用域是聲明此變量所在的文件,其餘的文件即便用extern聲明也不能使用。(2017.06.07)
 

數組名的值是指針常量。
數組有指針與下標兩種使用方式,下標毫不會比指針更有效率,但指針有時會比下標更有效率。
指針比下標更有效率的場合:在循環中一次一步地移動時。(《C和指針》2017.06.12)

 
 二維數組作函數參數:
void func2( int (*mat)[10] );
void func2( int mat[][10] );
 
二級指針的做用。
函數外面指針*p,要經過函數修改其指向的內容,函數形參應寫爲**p,不然做爲值傳遞,只是單純拷貝一份指針。你能夠改變指針所指向內存的值,但你不能改變原指針所對指向的內存位置。
 
 

 gcc C語言編譯:

       (1).預處理,生成預編譯文件(.文件):app

        Gcc –E hello.c –o hello.i
       (2).編譯,生成彙編代碼(.s文件):dom

        Gcc –S hello.i –o hello.s
       (3).彙編,生成目標文件(.o文件):
        Gcc –c hello.s –o hello.o
       (4).連接,生成可執行文件:
        Gcc hello.o –o hello分佈式


 

 目標文件反彙編objdump -S obj   或者 objdump -d obj函數

 各個段信息        objdump -s obj字體

 查看目標文件文件格式分段信息objdump -h obj ui

查看各個段大小size obj

 


 

函數指針:

  int f(int);

      int (*pf)(int) = &f;

      int ans = f(25);

      ans = (*pf)(25);     //將函數指針轉化爲函數名,和上一條左右一致

      ans = pf(25);         //這個轉換並非必須的,由於編譯器在執行函數調用操做符以前又會把它轉換回去2333


C++ 獲取指定目錄下全部文件目錄,這個函數是網上找的,但沒有提到64位和32位寫法的差異,我這裏是64位和32位兩個版本。

須要頭文件:

#include <io.h>
#include <iostream>
#include <vector>
using namespace std;

32位:

/*
** 做者:sonne
** 日期:2017-06-12
** 說明:讀取制定目錄下全部文件路徑和文件名
*/
void FileOperate::getFileNamesAndPaths(string path, vector<string>& files, vector<string>& file_name)
{
    //文件句柄  
    long   hFile = 0;
    //文件信息,聲明一個存儲文件信息的結構體  
    struct _finddata_t fileinfo;
    //字符串,存放路徑
    string p;
    if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1)//若查找成功,則進入
    {
        do
        {
            //若是是目錄,迭代之
            if ((fileinfo.attrib &  _A_SUBDIR))
            {
                if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
                     getFileNamesAndPaths(p.assign(path).append("\\").append(fileinfo.name), files, file_name);
            }
            //若是不是,加入列表  
            else
            {
                 files.push_back(p.assign(path).append("\\").append(fileinfo.name));
                 file_name.push_back(fileinfo.name);
             }
        } while (_findnext(hFile, &fileinfo) == 0);
        //_findclose函數結束查找
        _findclose(hFile);
    }
}

 

64位:

/*
 ** 做者:sonne
 ** 日期:2017-06-12
 ** 說明:讀取制定目錄下全部文件路徑和文件名
 */
void getFileNamesAndPaths(string path, vector<string>& files, vector<string>& file_name)
{
    //文件句柄  
    __int64   hFile = 0;
    //文件信息,聲明一個存儲文件信息的結構體  
    //struct _finddata_t fileinfo;
    struct __finddata64_t fileinfo;
    //字符串,存放路徑
    string p;
    if ((hFile = _findfirst64(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1)//若查找成功,則進入
    {
        do
        {
            //若是是目錄,迭代之
            if ((fileinfo.attrib &  _A_SUBDIR))
            {
                if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
                    getFileNamesAndPaths(p.assign(path).append("\\").append(fileinfo.name), files, file_name);
            }
            //若是不是,加入列表  
            else
            {
                files.push_back(p.assign(path).append("\\").append(fileinfo.name));
                file_name.push_back(fileinfo.name);
            }
        } while (_findnext64(hFile, &fileinfo) == 0);
        //_findclose函數結束查找
        _findclose(hFile);
    }
}

 


C++拷貝構造函數有兩種,深拷貝和淺拷貝。

淺拷貝只是簡單賦值成員變量。

若涉及堆內存,須要深拷貝。不然淺拷貝的方式會致使兩個指針指向同一個堆內存可能致使同一內存被釋放兩次。

能夠將拷貝構造函數寫爲private來禁止拷貝。


 刪除一個目錄下所有文件夾和文件:

bool removeDir(const char* szFileDir)
{
    std::string strDir = szFileDir; if (strDir.at(strDir.length() - 1) != '\\') strDir += '\\'; WIN32_FIND_DATA wfd; HANDLE hFind = FindFirstFile((strDir + "*.*").c_str(), &wfd); if (hFind == INVALID_HANDLE_VALUE) return false; do { if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if (_stricmp(wfd.cFileName, ".") != 0 && _stricmp(wfd.cFileName, "..") != 0) removeDir((strDir + wfd.cFileName).c_str()); } else { DeleteFile((strDir + wfd.cFileName).c_str()); } } while (FindNextFile(hFind, &wfd)); FindClose(hFind); RemoveDirectory(szFileDir); return true; }

 

獲取當前目錄(當前程序所在文件夾):

    char cPath[MAX_PATH+1];
    _getcwd(cPath, sizeof(cPath));

 

windows下vs編譯的C++程序要求獲取管理員權限:

打開項目-項目屬性-鏈接器-清單文件-UAC執行級別修改成requireAdministrator (/level='requireAdministrator')保存運行便可。

對你沒看錯,就這麼簡單!運行時自動要求提供管理員權限

 

獲取系統目錄:

    char str[MAX_PATH];
    GetSystemDirectory(str, MAX_PATH);
    std::cout << str << std::endl;

輸出C:\WINDOWS\system32

 


 

 禁止64位系統文件重定向:

    PVOID OldValue = NULL;
    Wow64DisableWow64FsRedirection(&OldValue); //……………… //……………… Wow64RevertWow64FsRedirection(OldValue);

 


字符串轉化爲guid:

typedef struct _GUID_TEMP {
    unsigned long Data1; unsigned short Data2; unsigned short Data3; int Data4[8]; } GUID_TEMP; BOOL LPCTSR2GUID(LPCTSTR szGUID, GUID &Guid) { memset(&Guid, 0, sizeof(Guid)); GUID_TEMP GUID_TEMP; int nRet = sscanf_s(szGUID, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", &GUID_TEMP.Data1, &GUID_TEMP.Data2, &GUID_TEMP.Data3, &GUID_TEMP.Data4[0], &GUID_TEMP.Data4[1], &GUID_TEMP.Data4[2], &GUID_TEMP.Data4[3], &GUID_TEMP.Data4[4], &GUID_TEMP.Data4[5], &GUID_TEMP.Data4[6], &GUID_TEMP.Data4[7] ); Guid.Data1 = GUID_TEMP.Data1; Guid.Data2 = GUID_TEMP.Data2; Guid.Data3 = GUID_TEMP.Data3; memcpy(&Guid.Data4[0], &GUID_TEMP.Data4[0], 1); memcpy(&Guid.Data4[1], &GUID_TEMP.Data4[1], 1); memcpy(&Guid.Data4[2], &GUID_TEMP.Data4[2], 1); memcpy(&Guid.Data4[3], &GUID_TEMP.Data4[3], 1); memcpy(&Guid.Data4[4], &GUID_TEMP.Data4[4], 1); memcpy(&Guid.Data4[5], &GUID_TEMP.Data4[5], 1); memcpy(&Guid.Data4[6], &GUID_TEMP.Data4[6], 1); memcpy(&Guid.Data4[7], &GUID_TEMP.Data4[7], 1); return (nRet == 11) ? TRUE : FALSE; }

 guid轉化爲字符串:

LPCTSTR GUID2LPCTS(GUID Guid) {
    static TCHAR szBuf[65] = { 0 }; _snprintf_s(szBuf, 64, _T("%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"), Guid.Data1, Guid.Data2, Guid.Data3, Guid.Data4[0], Guid.Data4[1], Guid.Data4[2], Guid.Data4[3], Guid.Data4[4], Guid.Data4[5], Guid.Data4[6], Guid.Data4[7] ); return szBuf; }

 


寫數據到bmp圖片:

int WriteBMP(const char* file, unsigned char* Input)
{
    unsigned char head[1078] = { /***************************/ //file header 0x42,0x4d,//file type //0x36,0x6c,0x01,0x00, //file size*** 0x0,0x0,0x0,0x00, //file size*** 0x00,0x00, //reserved 0x00,0x00,//reserved 0x36,0x4,0x00,0x00,//head byte*** 0x28,0x00,0x00,0x00,//struct size 0x00,0x00,0x0,0x00,//map width*** 0x00,0x00,0x00,0x00,//map height*** 0x01,0x00,//must be 1 0x08,0x00,//color count*** 0x00,0x00,0x00,0x00, //compression 0x00,0x00,0x00,0x00,//data size*** 0x00,0x00,0x00,0x00, //dpix 0x00,0x00,0x00,0x00, //dpiy 0x00,0x00,0x00,0x00,//color used 0x00,0x00,0x00,0x00,//color important  }; FILE *fh; if ((fh = fopen(file, "wb")) == NULL) return 0; int i, j; long num; num = IMAGE_X; head[18] = num & 0xFF; num = num >> 8; head[19] = num & 0xFF; num = num >> 8; head[20] = num & 0xFF; num = num >> 8; head[21] = num & 0xFF; num = IMAGE_Y; head[22] = num & 0xFF; num = num >> 8; head[23] = num & 0xFF; num = num >> 8; head[24] = num & 0xFF; num = num >> 8; head[25] = num & 0xFF; j = 0; for (i = 54; i < 1078; i = i + 4) { head[i] = head[i + 1] = head[i + 2] = j; head[i + 3] = 0; j++; } fwrite(head, 1, 1078, fh); for (i = 0; i <= IMAGE_Y - 1; i++) { fseek(fh, 1078 + (IMAGE_Y - 1 - i)*IMAGE_X, SEEK_SET); fwrite((Input + i * IMAGE_X), 1, IMAGE_X, fh); } fclose(fh); return 1; }

 


 讀文件到unsigned char數組:

int read_data_hex(unsigned char *buf, int length, const char *string)
{
    FILE *fp; fp = fopen(string, "rb"); if (NULL == fp) { return -1; } fread(buf, sizeof(unsigned char), length, fp); fclose(fp); fp = NULL; return 0; }

寫文件到unsigned char數組:

int write_data_hex(unsigned char * array, int length, const char *string)
{
    int i = 0; FILE *fp; fp = fopen(string, "wb+"); if (NULL == fp) { printf("file open Fail!\n"); return -1; } while (i < length) { fwrite(&array[i], sizeof(char), 1, fp); i++; } fclose(fp); return 0; }

 


 獲取年月日時分秒:

#include<time.h>
int main()
{
    time_t timep;
    struct tm *p; time (&timep); p=gmtime(&timep); printf("%d\n",p->tm_sec); /*獲取當前秒*/ printf("%d\n",p->tm_min); /*獲取當前分*/ printf("%d\n",8+p->tm_hour);/*獲取當前時,這裏獲取西方的時間,恰好相差八個小時*/ printf("%d\n",p->tm_mday);/*獲取當前月份日數,範圍是1-31*/ printf("%d\n",1+p->tm_mon);/*獲取當前月份,範圍是0-11,因此要加1*/ printf("%d\n",1900+p->tm_year);/*獲取當前年份,從1900開始,因此要加1900*/ printf("%d\n",p->tm_yday); /*從今年1月1日算起至今的天數,範圍爲0-365*/ }

帶多態性質的基類(含有virtual函數)應該聲明virtual析構函數。(《Effective C++》)


C修改開機密碼:

 

下面寫法須要獲取管理員權限

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

int main() {
    char user[256] = { 0 };
    const char *user_name = "sonne";
    const char *user_password = "huawei.123";
    char print[256] = { 0 };
    sprintf_s(user, "net user %s %s", user_name, user_password);
    system(user);
    sprintf_s(print, "已經將用戶名:%s 的密碼改爲了:%s", user_name, user_password);
    printf(print);
    system("pause");
    return 0;
}

 微軟的函數,可修改密碼,須要輸入舊密碼

NET_API_STATUS NET_API_FUNCTION NetUserChangePassword(
  IN LPCWSTR domainname,
  IN LPCWSTR username,
  IN LPCWSTR oldpassword,
  IN LPCWSTR newpassword
);

如何判斷輸入的開機密碼是否正確?

使用NetUserChangePassword函數,只不過舊密碼和新密碼參數同樣。而後判斷返回值。

 

 

 

關於這個函數的例程:

#ifndef UNICODE
#define UNICODE
#endif
#pragma comment(lib, "netapi32.lib")

#include <stdio.h>
#include <windows.h> 
#include <lm.h>

int wmain(int argc, wchar_t *argv[])
{
   DWORD dwError = 0;
   NET_API_STATUS nStatus;
   //
   // All parameters are required.
   //
   if (argc != 5)
   {
      fwprintf(stderr, L"Usage: %s \\\\ServerName UserName OldPassword NewPassword\n", argv[0]);
      exit(1);
   }
   //
   // Call the NetUserChangePassword function.
   //
   nStatus = NetUserChangePassword(argv[1], argv[2], argv[3], argv[4]);
   //
   // If the call succeeds, inform the user.
   //
   if (nStatus == NERR_Success)
      fwprintf(stderr, L"User password has been changed successfully\n");
   //
   // Otherwise, print the system error.
   //
   else
      fprintf(stderr, "A system error has occurred: %d\n", nStatus);

   return 0;
}

 


在全局做用域聲明的const變量是定義該對象的文件的局部變量。此變量只存在於那個文件中,不能被其餘文件訪問。
-----《C++ Primer》

引用與指針的區別:

1. 指針是一個實體,而引用僅是個別名;
2. 引用使用時無需解引用(*),指針須要解引用;
3. 引用只能在定義時被初始化一次,以後不可變;指針可變;
4. 引用沒有 const,指針有 const;
5. 引用不能爲空,指針能夠爲空;
6. 「sizeof 引用」獲得的是所指向的變量(對象)的大小,而「sizeof 指針」獲得的是指針自己(所指向的變量或對象的地址)的大小;
7. 指針和引用的自增(++)運算意義不同;
8.從內存分配上看:程序爲指針變量分配內存區域,而引用不須要分配內存區域。

 


動態連接庫和COM組件的區別

     1動態連接庫的表現形式只能是dll[變態該名的除外], COM組件的表現形式能夠是dll也能夠是exe。

     注:其實字體、驅動等也算是動態連接庫的一種,這裏略去...

     2 動態連接庫的生成和編譯器及系統相關,在Windows/Linux下系統,須要分別編譯才能使用。

          COM組件是二進制編碼,在Windows和Linux下能夠直接使用,不須要從新編譯。

     3 COM組件是按照COM規範實現的dll或者exe;動態連接庫是一個能夠導出函數的函數集合。

     4 動態連接庫只能在本機被調用,COM組件支持分佈式使用。

相關文章
相關標籤/搜索