(멀티바이트->유니코드->TCHAR)


strcpy -> wcscpy -> _tcscpy (문자열을 복사)

strncpy -> wcsncpy -> _tcsncpy ( 사이즈 만큼 복사)

strlen -> wcslen -> _tcslen (문자열 길이 확인)

strcat -> wcscat -> _tcscat (두 문자열 이어 붙이기)

strncat -> wcsncat -> _tcsncat (사이즈 만큼 이어 붙이기)

strcmp -> wcscmp -> _tcscmp (문자열 비교) (반환 값(-1, 0, 1))

strncmp -> wcsncmp -> _tcsncmp ( 사이즈 만큼 문자열 비교)

stricmp -> wcsicmp -> _tcsicmp (대소문자를 구별하지 않고 문자열을 비교)

strnicmp -> wcsnicmp -> _tcsnicmp (사이즈 만큼 대소문자를 구별하지 않고 문자열을 비교)

strchr -> wcschr -> _tcschr (문자 찾기)

strrchr -> wcsrchr -> _tcsrchr (문자 찾기 (문자열 끝에서 부터 검색))

strstr -> wcsstr -> _tcsstr (문자열 찾기)

strpbrk -> wcspbrk -> _tcspbrk (문자 찾기 (두번째 인수를 찾고자 하는 문자들의 집합(문자열)으로 구성)

strtok -> wcstok -> _tcstok (문자열 자르기 (두번째 인수를 집합(문자열)으로 구성 가능)) => 해당 문자가 NULL로 치환 됨

strset -> wcsset -> _tcsset (문자 치환, 첫째 인수의 모든 문자를 두번째 인수 문자로 변경함) => "abc" -> "bbb"

strnset -> wcsnset -> _tscnset (사이즈 만큼 문자 치환)

strupr -> wcsupr -> _tcsupr (대문자로 치환)

strlwr -> wcslwr -> _tcslwr (소문자로 치환)

strrev -> wcsrev -> _tcsrev (문자열 역정렬) => "가나다라마" -> "마라다나가"



출처: http://mrhook.co.kr/202 [Mr. 후크의 잡동사니]

블로그 이미지

란마12

,
형식 이름바이트기타 이름값의 범위
int4signed–2,147,483,648~2,147,483,647
unsigned int4unsigned0 ~ 4,294,967,295
__int81char–128~127
unsigned __int81unsigned char0 ~ 255
__int162short, short int 및 signed short int–32,768~32,767
unsigned __int162unsigned short, unsigned short int0 ~ 65,535
__int324signed, signed int 및 int–2,147,483,648~2,147,483,647
unsigned __int324unsigned, unsigned int0 ~ 4,294,967,295
__int648long long, signed long long–9,223,372,036,854,775,808~9,223,372,036,854,775,807
unsigned __int648unsigned long long0 ~ 18,446,744,073,709,551,615
bool1없음false 또는 true
char
1
없음
–128~127(기본값)
/J를 사용하여 컴파일하는 경우 0~255
signed char1없음–128~127
unsigned char1없음0 ~ 255
short2short int, signed short int–32,768~32,767
unsigned short2unsigned short int0 ~ 65,535
long4long int, signed long int–2,147,483,648~2,147,483,647
unsigned long4unsigned long int0 ~ 4,294,967,295
long long8없음(그러나 __int64와 동일)–9,223,372,036,854,775,808~9,223,372,036,854,775,807
unsigned long long8없음(그러나 unsigned __int64와 동일)0 ~ 18,446,744,073,709,551,615
enumvaries없음자세한 내용은 이 문서의 설명을 참조하십시오.
float4없음3.4E+/-38(7개의 자릿수)
double8없음1.7E+/-308(15개의 자릿수)
long doubledouble과 동일없음double과 동일
wchar_t2__wchar_t0 ~ 65,535

https://msdn.microsoft.com/ko-kr/library/s3f49ktz(v=vs.100).aspx


블로그 이미지

란마12

,

class Base {

    int const constant;

public:

    virtual ~Base() = 0; // Makes this an abstract base class.

protected:

    Base(int c) : constant(c) { }

};


// Must be implemented!

Base::~Base() { }


class Derived : public Base {

    int const constant2;

public:

    //static const int constant1; //error C2057: 상수 식이 필요합니다.

    enum { constant1 = 1 };

    int aaa[constant1];

    Derived() : Base(42), constant2(2) { }

};

'language > C/C++' 카테고리의 다른 글

문자열 관련 함수  (0) 2018.09.11
데이터타입별 범위  (0) 2015.07.13
const  (0) 2012.05.21
Use 'static const' instead of '#define'  (0) 2011.12.06
2차원 배열이 더블포인터인가?  (0) 2010.11.10
블로그 이미지

란마12

,

const

language/C/C++ 2012. 5. 21. 16:11

void main(void)

{

    const int a = 1;    // a에 대해서 상수로 보호

    //a = 3;        // Compile Error C3892: 'a' : const인 변수에 할당할 수 없습니다.

 

    int const a2 = 1;   // a2에 대해서 상수로 보호

    //a2 = 3;       // Compile Error C3892: 'a2' : const인 변수에 할당할 수 없습니다.

 

    const int *b = NULL;    // *b에 대해서 상수로 보호

    b = &a;

    //*b = 1;       // Compile Error C3892: 'b' : const인 변수에 할당할 수 없습니다.

 

    int const *c = NULL;    // *c에 대해서 상수로 보호

    c = &a;

    //*c = 1;       // Compile Error C3892: 'c' : const인 변수에 할당할 수 없습니다.

 

    int aa = 2;


    int* const d = &aa;     // d에 대해서 상수로 보호

    //d = &aa;      // Compile error C3892: 'd' : const인 변수에 할당할 수 없습니다.

    *d = 3;

 

    const int* const e = &aa;   // *e와 e에 대해서 상수로 보호

    //e = &aa;      // Compile error C3892: 'e' : const인 변수에 할당할 수 없습니다.

    //*e = 5;       // Compile error C3892: 'e' : const인 변수에 할당할 수 없습니다.

 

    int const* const f = &aa;   // *f와 f에 대해서 상수로 보호

    //f = &aa;      // Compile error C3892: 'f' : const인 변수에 할당할 수 없습니다.

    //*f = 5;       // Compile error C3892: 'f' : const인 변수에 할당할 수 없습니다.

 

    printf( "b = %d\n", *b );

    printf( "c = %d\n", *c );

    printf( "d = %d\n", *d );

    printf( "e = %d\n", *e );

    printf( "f = %d\n", *f );

[출처] [c/c++] const 위치에 따른 상수 보호 범위|작성자 슈퍼베리코더



int nTmp1 = 0;

int nTmp2 = 0;


const int* pnConst1 = 0;

pnConst1 = &nTmp1; 

*pnConst1 = 0; //err


int* const pnConst2 = 0;

pnConst2 = &nTmp1; //err

*pnConst2 = 0;


const int* const pnConst3 = 0;


const int& rnConst1 = nTmp1;

rnConst1 = 0; //err

rnConst1 = nTmp2; //err


int& const rnConst2 = nTmp1; //const 무의미?

rnConst2 = 0;

rnConst2 = nTmp2;



const int& MyClass::foo(const int& a_rn) const;

마지막 const는 this를 다음과 같이 만듬.

const MyClass * const this;

즉, this->var = xxx; //err

블로그 이미지

란마12

,

Which one is better to use among the below statements in c:

static const int var=5; 

or

#define var 5 



















It depends on what you need the value for.
  1. static const int var = 5;
  2. #define var 5
  3. enum { var = 5 };

Ignoring issues about the choice of name, then:

  • If you need to pass a pointer around, you must use (1).
  • Since (2) is apparently an option, you don't need to pass pointers around.
  • Both (1) and (3) have a symbol in the debugger's symbol table - that makes debugging easier. It is more likely that (2) will not have a symbol, leaving you wondering what it is.
  • (1) cannot be used as a dimension for arrays at global scope; both (2) and (3) can.
  • (1) cannot be used as a dimension for static arrays at function scope; both (2) and (3) can.
  • Under C99, all of these can be used for local arrays. Technically, using (1) would imply the use of a VLA (variable-length array), though the dimension referenced by 'var' would of course be fixed at size 5.
  • (1) cannot be used in places like switch statements; both (2) and (3) can.
  • (2) can change code that you didn't want changed because it is used by the preprocessor; both (1) and (3) will not have unexpected side-effects like that.
  • You can detect whether (2) has been set in the preprocessor; neither (1) nor (3) allows that.

So, in most contexts, prefer the 'enum' over the alternatives. Otherwise, the first and last bullet points are likely to be the controlling factors - and you have to think harder if you need to satisfy both at once.

If you were asking about C++, then you'd use option (1) - the static const - every time.

http://stackoverflow.com/questions/1674032/static-const-vs-define-in-c

'language > C/C++' 카테고리의 다른 글

클래스내의 배열변수의 크기를 상수로 지정하고 싶을 때  (0) 2014.12.11
const  (0) 2012.05.21
2차원 배열이 더블포인터인가?  (0) 2010.11.10
메모리오류 시 디버거가 설정해 주는 값  (0) 2010.09.17
지침  (0) 2010.09.17
블로그 이미지

란마12

,

충격적인 사실은.. C/C++에는 2차원 배열이 없다는 것입니다. 물론, 3차원, 4차원 배열도 없습니다. C/C++에는 1차원의 선형 배열만 있을 뿐입니다.
그렇다면 우리가 2차원, 3차원 배열이라고 사용하는 것은 무엇일까요?
C/C++은 2차원 이상의 배열은 '배열을 원소로 가지는 배열'로서 구현하고 있습니다.
즉, int array[3][256];라고 했을때, 이것은 3*256의 배열이 아니라, int[256]의 배열을 원소로 하여 그 배열이 3개 연속으로 있는 구조를 취합니다. (행중심 배열이라고 하지요)
C/C++에서 배열의 이름은 그 배열의 첫번째 원소에 대한 포인터입니다.
즉, int a[3]의 경우, a라는 이름은 int형에 대한 포인터, 즉 int*타입이 되지요.
그렇다면, int array[3][256];라고 했을 때, array라는 이름은 배열의 첫번째 원소에 대한 포인터가 되어야 옳습니다. 이때, 2차원 이상의 배열은 배열을 원소로 가지는 배열이라고 했습니다. 즉, 이때, array라는 배열의 원소는 int형의 원소가 256개 있는 배열이 되지요. 따라서 array라는 이름은 int[256]에 대한 포인터, 즉 int*[256] 타입이 되어야 옳습니다. 이는, 포인터 연산을 위해서는 포인터가 가리키는 대상의 크기가 얼마인지가 확정되어야 하기 때문이지요. 이를테면, p가 int*타입일 경우, p++이라고 하면 int형의 크기만큼 증가하게 됩니다. 만약, p가 int array[3][256]를 가리킨다고 하면, p++이라고 했을 때, array의 각 원소의 크기만큼 증가해야 합니다, 즉, 배열의 각 원소의 크기를 컴파일러가 알 필요가 있다는 얘기지요. 따라서 2차원 배열의 열의 크기를 알아야 합니다. (하나의 열이 배열의 원소 하나이기 때문이지요)
따라서 2차원 배열을 인자로 받아들이는 함수는 다음과 같은 프로토타입은 유효하지 않습니다.
Matrix( int **k);
Matrix( int k[][]);
Matrix( int (*k)[]);
이들 모두 2차원 배열의 열의 크기가 무엇인가를 알려주는 힌트가 하나도 없기 때문이지요.
제대로 선언하려면 열의 크기를 알려주는 힌트가 필요합니다. 다음과 같이 말이죠.
Matrix( int k[3][256]);
Matrix( int k[][256]);
Matrix( int (*k)[256]);
단, Matrix( int *k[256]); 과 같은 표현은 유효하지 않습니다. 이 표현은 int*의 배열을 인자로 받는다는 선언이지, int형의 256개짜리 배열에 대한 포인터를 인자로 받는다는 표현이 아니지요.

'포인터는 포인팅하는 대상의 크기가 분명해야 한다'는 원칙



int a[4];
int *p = a;
일때 a[0] == p[0], a[1] == p[1] 이라고 하는 것을 보고

in a[3][4]; 일 때
int **p =a;
이고 a[0][0] == p[0][0], a[1][2]== p[1][2]로 알고 계시는 분들이 있으십니다.
혹은 왜 이게 안되는지 궁금해 하십니다.

그래서 이런 글을 올립니다. 참고하세요

배열의 등가포인터 의미와 생성 그리고 활용에 대하여 다룹니다.

자 이런 배열이 있습니다
int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
이때 배열의 이름 a는 배열의 정의상 배열의 첫요소의 주소입니다.
그러면 이는 배열의 첫요소 즉, a[0][0]의 주소 즉, &a[0][0] 일까요?
아니면 &a[0] 일까요? 값만 놓고 보면 둘 다 같은 값이 나옵니다.
그러면 의미상 정확하게 맞는 표현은 무엇일까요?

int a[3][4] 배열은 요소 12개 짜리 1차원 배열이 아닙니다.
메모리에는 12개의 숫자가 연속해서 존재하기는 하나 이를
편의를 위하여 2차원 배열처럼 생각하는 거지요

고로 int a[3][4]는 요소수 3개 짜리 배열입니다. 즉, 3칸짜리 배열이지요

그런데 이 배열은 각 칸칸마다 뭐가 들어 있냐면 정수가 있는것이 아니라
int [4] 즉, int 4개짜리 배열이 들어있는 겁니다.

따라서 이 배열의 요소수는 3개이고 이 배열의 첫요소는 a[0] 가 됩니다.
고로 배열명 a == &a[0]라고 해야합니다.

그러면 어차피 값은 &a[0][0]나 &a[0]이나 같은데 왜 꼭 &a[0]가 맞다고 할까요?
자 다음을 보시지요

int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
int *p = a;
int (*q)[4] = a;
int **r = a;

세개의 포인터에 배열명 a를 담았습니다. 어느것이 옳을까요?
여기서 옳다는 것은 단지 대입이 되느냐 아니냐가 아니라
컴파일리 에러, 경고 없는 경우입니다.

사실 대부분 컴파일러는 int *p = a; 는 경고를 내거나 엄격한 컴파일러는
에러를 냅니다. 고로 에러, 경고를 막으려면 casting을 써서
int *p = (int *)a; 라고 해야 합니다.

그러나 두번째 int (*q)[4] = a; 는 에러, 경고 나지 않습니다.
즉, 두개는 완벽히 일치하는 데이터 타입이라는 뜻이지요...

세번째 2중 포인터는 int **r = p;는 역시 첫번째와 마찬가지로
타입이 다른 주소가 대입되므로 에러 혹은 경고가 납니다.
정상이려면 int **r = (int **)a; 하셔야 합니다.

자 왜 두번째 포인터만 정상일까요?
위에서 얘기 했듯이 int a[3][4] 일때 배열명 a는 &a[0]의 주소인데
a[0]은 a배열의 첫요소 즉, 3칸 짜리 배열에는 int [4]
즉, int 4개 짜리 배열이 들어 있으므로
a[0]는 그 속의 int [4] 배열의 이름이 됩니다.

고로 &a[0]는 바꿔 말하면 int [4] 배열의 주소이므로
타입은 int (*)[4] 라고 쓸수 있습니다.
그런데 a == &a[0] 이니 결국 배열 이름은 int (*)[4] 와 같은 타입입니다.

그러므로 이러한 주소를 받는 포인터는 int (*q)[4] 로 선언하게되고
int (*q)[4] = a; 가 성립하는 것입니다.

그럼 다시 다음에서 봅시다.

int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
int *p = (int *)a;
int (*q)[4] = a;
int **r = (int **)a;

이렇게 강제로라도 a를 대입했다면 이 포인터들로
배열에 있는 a[1][2] 즉,  7을 억세스 하려면 어떻게 할까요?

int *p는 현재 값이 정수 즉, 1의 주소를 갖으므로
그리고 정수(int)의 포인터 이므로
printf("%d\n", *(p+6)); 하거나 혹은 [ ] 연산자를 이용하여
printf("%d\n", p[6]); 으로 해야 합니다.

그러나 두번째는 int (*q)[4]의 현재값이 {1,2,3,4} 배열의 주소이므로
a[1][2]와 동일한 표현은 q[1][2] 가 됩니다.
이것이 왜 이렇게 되는지는 다차원 배열을 공부하시면 됩니다.

즉,
int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
에서 a[1][2] 와 같은 값을 억세스 하기 위하여 
int *p = (int *)a; 로 하면 p[6]  혹은 *(p+6)
int (*q)[4] = a; 로 하면 q[1][2] 로 됩니다.
두 방법중 어떤것이 이해가 쉽습니까? 

이와같이 배열의 이름을 대입받을 때 에러, 경고, 캐스팅 없이 대입 가능한
포인터를 배열의 등가포인터라고 하고 등가포인터가 배열의 이름을 받으면
그때부터는 포인터가 배열과 표현식이 동일하게 사용가능합니다.

물론 그렇다고 이것이 완전히 동일해 지는것은 아닙니다.
배열은 배열이고 포인터는 포인터입니다. 단지 배열명을 갖는 포인터이지요

단, 억세스는 간접연산(포인터로 인하여)이므로 억세스 속도는 배열보다 느립니다.

그럼 1차원 함수에 넘기는 경우를 보지요...

void main(void)
{
   int a[4] = {1,2,3,4};
   func(a);
}
라고 할때 func 함수는 넘겨받은 배열의 이름을 이용하여
배열내의 a[2]인 3을 인쇄한다고 합시다.

그럼 어떻게 하나요?
void func(int *p)
{
    printf("%d\n", p[2]);
}
라고 할것입니다.

 이 상황을 잘보면 

(1) main에서 func를 호출하면서 넘긴것은 배열의 이름 a입니다.
1차원 배열이므로 이 이름은 첫요소의 주소 즉, &a[0]  이고 a[0]는 정수 1이므로
int * 타입입니다.

(2) 고로 func에서는 이런 배열의 이름과 등가인 int *p로 받는것입니다.
즉, int *p = a; 가 가능하므로 int *로 한것이지요
고로 p는 표현식에서 a 배열과 동일하므로 a[1] ==p[1]이 됩니다.

즉, 배열은 전체를 넘기지 못하고 그 첫요소의 주소(배열명)를 넘기므로
이를 등가포인터로 받고 활용은 마치 배열인듯이 하는 겁니다.

이것이 등가포인터의 활용이지요...

그럼 2차원 배열을 넘기면 어떻게 되나요?

int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
func(a);
에서 a[1][2] 와 값을 인쇄하는 함수는 어떻게 만드나요?

(1) int func(int *p)
(2) int func(int (*p)[4]);
(3) int func(**p); 어느것이 옳을까요?

만약 1처럼 하면?

func(a); 하면 경고가 발생하므로
억지로 캐스팅 하여 func((int *)a); 로 해야 합니다.
그리고 함수는 이렇게 만들지요

int func(int *p)
{
    printf("%d\n", p[6]);
    또는 
    printf("%d\n", *(p+6));
}

그런데 2번처럼 하면 아까 얘기했듯이 int (*p)[4]는 배열명 a 와 등가이므로
int (*p)[4] = a; 가 가능합니다.

고로 활용이 마치 a 배열처럼 되므로 다음과 같이 됩니다.

int func(int (*p)[4])
{
    printf("%d\n", p[1][2]);
}

3번 처럼 단순히 2중포인터라고 생각한다면?
이거 골치아퍼집니다.
아마 세가지 방법에서 제일 골치아프겠네요
한번 직접 해보세요...

이때 p[1][2]는 절대 배열이 아닙니다. p는 엄연한 포인터입니다.
그럼 어떤것이 쉽고 정상적인 방법일까요? 

배열을 넘기고(배열명을 넘기는 거지만) 이를 등가 포인터로 받고
그리고 이를 활용할때는 마치 원래의 배열처럼 하는것 이게 등가포인터를 활용한 겁니다.

다음은 2차원 배열을 넘기고  배열요소의 전체 합을 구하는 함수를 설계합니다.
역시 등가 포인터를 활용합니다.

결국

void main(void)
{
    int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12}; 
    printf(""%d\n", sum(a));
}

int sum(int (*p)[4])
{
    int a = 0, i, j;
    for(i=0; i<3; i++)
   {
       for(j=0; j<3; j++)
      {
           a += p[i][j];
      }       
   }
  return a;
}

다시한번 말씀드리지만
위와 같이 배열을 다른 함수로 넘기거나 다른함수에서 리턴하거나
할때 배열명을 넘기고 받기는 포인터(등가포인터)로 받고
활용은 넘겨준 배열과 동일하게 하는것이 좋습니다.
이런 포인터를 등가포인터라고 합니다.

결국 등가포인터를 이용하면 배열, 함수를 함수로 넘기거나 함수 리턴으로 줄 때
매우 쉬워 집니다.

참고로 다음은 등가적인 포인터의 예를 보입니다.

(1) int a[4]  ==> int *p
(2) int *a[4] ==> int **p
(3) int a[3][4] ==> int (*p)[4]
(4) int a [2][3][4] ==> int (*p)[3][4]
(5) int *(*a[3])(int) ==> int *(**p)(int)
...
위에서 등가포인터 만드는 공식(?) 내지는 꼼수를 찾아보세요.

http://kin.naver.com/open100/detail.nhn?d1id=1&dirId=1040101&docId=545702&qb=MuywqOybkCDrsLDsl7TsnbQg642U67iU&enc=utf8&section=kin&rank=1&search_sort=0&spq=0&pid=gLF%2Bvsoi5T0ssZOkRHosss--332099&sid=TNkPTesN2UwAABudDlI

'language > C/C++' 카테고리의 다른 글

클래스내의 배열변수의 크기를 상수로 지정하고 싶을 때  (0) 2014.12.11
const  (0) 2012.05.21
Use 'static const' instead of '#define'  (0) 2011.12.06
메모리오류 시 디버거가 설정해 주는 값  (0) 2010.09.17
지침  (0) 2010.09.17
블로그 이미지

란마12

,
  • 0xcccccccc (3435973836) - 초기화 되지 않은 지역변수.
  • 0xcdcdcdcd (3452816845) - 초기화되지 않은 힙에 할당된 메모리.
  • 0xdddddddd (3722304989) - 힙에서 free된 메모리.
  • 0xfeeefeee (4277075694) - 힙에서 free된 메모리.
  • 0xfdfdfdfd (4261281277) - 힙에 할당된 메모리의 초과범위(할당된 메모리의 양쪽 끝)
  • 'language > C/C++' 카테고리의 다른 글

    클래스내의 배열변수의 크기를 상수로 지정하고 싶을 때  (0) 2014.12.11
    const  (0) 2012.05.21
    Use 'static const' instead of '#define'  (0) 2011.12.06
    2차원 배열이 더블포인터인가?  (0) 2010.11.10
    지침  (0) 2010.09.17
    블로그 이미지

    란마12

    ,

    지침

    language/C/C++ 2010. 9. 17. 10:21

    1. 클래스나 구조체같은 변수는 무조건 포인터로 선언하자.
        : 생성/소멸 시점을 명확하게 제어할 수 있다.

    2. 클래스 초기화는 생성자에서 하지 말고 초기화/해제 함수를 따로 만들어 하자.
       특히 생성자에서 다른 생성자를 호출하면 안된다. 다른 인스턴스의 생성자가 호출되어 의미없는 동작이 되어버림.


    블로그 이미지

    란마12

    ,