Windows開発実録

5158 ワード

ご飯は一口ずつ...
プリコンパイルPrecompiler
Compiling C++ code is a long, slow process, especially compiling window API or other API library(boost).The Microsoft compiler can ameliorate this problem with a simple trick called precompiled headers. The trick is pretty slick: although every CPP file can potentially and legally give a sligthly different meaning to the chain of header files included on top of each Cpp file (by things like having different macros #define'd in advance of the includes, or by including the headers in different order), that is most often not the case. Most of the time, we have dozens or hundreds of included files, but they all are intended to have the same meaning for all the Cpp files being compiled in your application.
The trick consists on designating a special header file as the starting point of all compilation chains, the so called 'precompiled header' file, which is commonly a file named stdafx.h simply for historical reasons.
There are two steps to use precomplie in visual studio.
1. Create "stdafx.h"and "stdafx.cpp". Precompiler header"in project's properties to be "Create/Yc". Simply list all your big huge headers for your APIs in your stdafx.h file, in the appropriate order, and then start each of your CPP files at the very top with an  #include "stdafx.h" , before any meaningful content (just about the only thing allowed before is comments). In "stdafx.cpp", just include the "stdafx.h" and nothing else.
2. Make sure that Including "stdafx.h"as the first line in all other source code (.cpp files). 
3. Change the "Precompiler header"in project's properties to be "Create/Yc". And then build the project in order to create projectname.pch file. So far, next time, when you compile your code, compiler will choose to retrieve obj file fromprojectname.pch other than recompile all the headers which are included in "stdafx.h".
4. Change the "Precompiler header"in project's properties to be "Use/Yu". 
Note: 
It's recommand to include the basic header such as header defined in STL, windows's basic api ("windows.h") or other third libraries (boost) in "stdafx.h".
If you met the compiler error: c1038 cannot open precompiled header file: 'debug\xxx.pch
', please change the precompiler header to be "create/Yc". 
文字列コピーの正しい方法
文字列のコピーは、strcpy、strncpyまたはmemcpyメソッドを使用することにほかならない.たとえば、コードは次のようになります.
strcpy 
char *strcpy( char *strDestination, const char *strSource );

The strcpy function copies strSource, including the terminating null character, to the location specified by strDestination. No overflow checking is performed when strings are copied or appended. The behavior of strcpy is undefined if the source and destination strings overlap. すなわち、ソース文字列がターゲット文字列よりも少ない場合に正しく使用され、nullで終了することができる.ただし、オーバーフロー処理は提供されません.次のコードに示すように、非定義例外が発生します.
#define BufLen 5
typedef char Buffer[BufLen];

char pp[] = {"helloworld"};
Buffer b1;
strcpy(b1, pp);
cout<<b1<<endl;

strncpy
char *strncpy( char *strDest, const char *strSource, size_t count );
ソース長がターゲット長以下である場合、nullを含まないソース長のすべての文字をコピーするだけです.しかし、ソース長がターゲット長より大きい場合、nullの終了がなく、ターゲット長の内容が切り取られます.overflowによる非定義の影響をもたらします.
memcpy
void *memcpy(
   void *dest,
   const void *src,
   size_t count 
);
唯一長さが長すぎる場合、指定した長さをコピーし、非定義の動作を引き起こすことはありません(overflowは発生しません)が、nullを自分で定義する必要があります.長さが長すぎる場合は、ターゲットの長さより短い場合はstrlen(src)+1を使用してnullもコピーできます.
推奨される使用方法は次のとおりです.
static const int BufLen = 127;
typedef struct _VAABuffer
{
	int len;
	char data[BufLen+1];
	_VAABuffer():len(0)
	{
		memset(data, 0, sizeof(data));
	}
	_VAABuffer(_VAABuffer& rhs)
	{
		memcpy(data, rhs.data, sizeof(data));
		len = rhs.len;
	}
	_VAABuffer(const char * src)
	{
		if (strlen(src) > BufLen)
		{
			memcpy(data, src, BufLen);
			data[BufLen] = '\0';
		}
		else
			strcpy(data, src);
		len = strlen(data);
	}
	_VAABuffer& operator=(_VAABuffer rhs)
	{
		memcpy(data, rhs.data, sizeof(data));
		len = rhs.len;
		return *this;
	}
	_VAABuffer& operator=(const char * src)
	{
		if (strlen(src) > BufLen)
		{
			memcpy(data, src, BufLen);
			data[BufLen] = '\0';
		}
		else
			strcpy(data, src);
		len = strlen(data);
		return *this;
	}
}VAABuffer;