2011. 10. 12. 20:04

"%[parameter][flags][width][.precision][length]type"

Parameter 

Character 

Description 

n$ 

파라미터 지정

This is a POSIX extension and not in C99.

Example: printf("%2$d %1$#x %1$d",16,17) produces "17 0x10 16"

 

Flags

Character 

Description 

+ 

양수 '+', 음수 '-' 기호 출력. (디폴트 : 아무것도 표시 안함)

- 

좌측 정렬

# 

8진수, 16진수 출력시 각각 0과 0x를, 실수의 경우 소수점 이하 0을 출력

' '공백

출력할 크기가 0보다 클 때 수의 앞에 빈 칸 하나 출력

0 

빈공간을 0으로 체움

 

Width

Character

Description 

* or N

폭 지정 (*와 같은 경우 숫자와 대응)

Example: printf("%*d", 5, 10) will result in " 10" being printed with a width of 5.

 

Precision

Character 

Description 

* or N

정밀도 지정 (*와 같은 경우 숫자와 대응)

정수의 경우-> 지정한 숫자보다 개수가 작을 경우 나머지 0으로 표시

실수의 경우-> 소수점 자리 수

문자열의 경우-> 지정한 개수만큼의 문자 표시

Example: printf("%.*s", 3, "abcdef") will result in "abc" being printed.

 

Length

Character 

Description 

h 

정수 자료형 감소 (int-> short)

hh 

정수 자료형 2번 감소 (int-> short-> char)

l 

정수 자료형 증가(int-> long)

ll 

정수 자료형 2번 증가(int-> long-> long long)

L 

실수 자료형 증가 (long -> long double)

z 

For integer types, causes printf to expect a size_t sized integer argument.

j 

For integer types, causes printf to expect a intmax_t sized integer argument.

t 

For integer types, causes printf to expect a ptrdiff_t sized integer argument.

 

Type

Character 

Type

Description 

d, i 

int 

부호 있는 10진수 정수

u 

unsigned int 

부호 없는 10진수 정수

o 

unsigned int 

부호 없는 8 진수 정수

x, X 

unsigned int 

부호 없는 16진수 정수

f, F 

double 

10진수 방식의 부동 소수점 실수

e, E 

double 

지수 형식으로 출력

g, G 

double 

%e와 %f 중 짧은 쪽, 소수점에 이어지는 0은 생략

c 

int 

값에 대응하는 문자

s 

char * 

문자열

p 

void * 

포인터 주소값

n 

int * 

포인터 주소값

% 

literal '%' 

리터럴 '%' 문자( 플래그, 폭, 정밀, 길이 허용 안함)

Posted by devanix
2011. 9. 8. 05:50

'Programming > C' 카테고리의 다른 글

printf 출력 서식  (0) 2011.10.12
The C Library Reference Guide  (0) 2011.09.08
비트 제어 - 설정, 클리어, 반전, 검사, 추출  (0) 2011.07.29
다시 체계적으로 배우는 C언어 포인터  (0) 2011.07.07
연산자 우선순위  (0) 2010.05.05
Posted by devanix
2011. 9. 8. 05:37
Posted by devanix
2011. 7. 29. 15:34

[ 비트 설정 ]

▶ 특정 비트를 1로 설정 : 1과 |(or)연산.

▷ 5번 비트를 1로 설정>

  

0101_0101

OR( | )

0010_0000

  

0111_0101

 

위의 연산을 코드화 : a |= 0x00100000;

▷ 위의 0x001_0000은 0x1(0x000_0001)을 5번 쉬프트한 값과 같다.

a |= 0x1 << 5;

   

▷ 5,3,2번 비트를 1로 설정>

  

0101_0101

OR( | )

0010_1100

  

0111_1101

 

위의 연산을 코드화 : a |= (0x1<<5)+(0x1<<3)+(0x1<<2);

▷ 3,2번 비트는 연속된 비트이기 때문에 0x3으로 묶어줄 수 있다.

a |= (0x1<<5)+(0x3<<2);

   

[ 비트 클리어 ]

▶ 특정 비트 클리어 : 0과 &연산.

▷ 1을 원하는 위치로 쉬프트하고 그 값에 대해 ~(NOT)연산을 해서 0으로 만듬.

(0x0000, 0x0도 모두 0이기 때문에 0으로 자릿수를 표현할 수 없음)

0x1 << 5

0x0010_0000

~(0x1<<5)

0x1101_1111

▷ 2번 비트를 0으로 클리어>

  

0101_0101

AND(&)

1111_1011

  

0101_0001

위의 연산 코드화 : a &= ~(0x1<<2);

   

▷ 5,3,2번 비트 클리어>

  

0101_0101

AND(&)

1101_0011

  

0101_0001

위의 연산 코드화 : a &= ~((0x1<<5)+(0x3<<2));

   

[ 비트 반전 ]

▶ 특정 비트 반전 : 1과 ^연산. ( ^연산은 두 피연산자가 같으면 0, 다르면 1로 설정)

▷ 5번 비트 반전 >

  

1111_0101

XOR(^)

0010_0000

  

1101_0101

위의 연산 코드화 : a ^= 0x1<<5

   

▷ 5,3,2번 비트 반전 >

  

1111_0101

XOR(^)

0010_1100

  

1101_1001

위의 연산 코드화 : a ^= (0x1<<5)+(0x3<<2);

   

[ 비트 검사 ]

▶ 특정 비트가 0인지 1인지 검사.

▷ 5번째 비트가 0인지 1인지 검사 : a & (0x1 << 5)

   

[ 비트 추출 ]

▶ 특정 비트만 추출.

▷ [6:4] 비트만 추출하고 싶다면 : (a>>4) & 0x7

   

   

[ bit_macro.h ]

/* 한 비트 클리어 */
#define clear_bit(data, loc)    ((data) &= ~(0x1 << (loc)))
/* 연속된 여러 비트 클리어 */
#define clear_bits(data, area, loc)     ((data) &= ~((area) << (loc)))
 
/* 한 비트 설정 */
#define set_bit(data, loc)      ((data) |= (0x1 << (loc)))
/* 연속된 여러 비트 설정 */
#define set_bits(data, area, loc)  ((data) |= ((area) << (loc)))
 
/* 한 비트 반전 */
#define invert_bit(data, loc)   ((data) ^= (0x1 << (loc)))
/* 연속된 여러 비트 반전 */
#define invert_bits(data, area, loc)    ((data) ^= ((area) << (loc)))
 
/* 비트 검사 */
#define check_bit(data, loc)    ((data) & (0x1 << (loc)))
 
/* 비트 추출 */
#define extract_bits(data, area, loc)   (((data) >> (loc)) & (area))

   

 

[ bit_test.c ]

#include <stdio.h>
#include "bit_macro.h"

void bitdisp(int c) {
    int i;

    for (i=7; i>=0; i--)
        printf("%1d", check_bit(c, i)? 1:0);

    putchar('\n');
}

int main(void) {
    unsigned char a = 0xf0;     // 11110000(₂)
    unsigned char b;

    printf("a 2진수로 출력 : "); bitdisp(a);
    puts("------------------------------------");
clear_bit(a, 5); /* 5번 비트 클리어 */ printf("5번 비트 클리어 : "); bitdisp(a); clear_bits(a, 0x7, 3); /* 5,4,3번의 연속 3비트 클리어 */ printf("5,4,3번 비트 클리어 : "); bitdisp(a); putchar('\n'); set_bit(a, 5); /* 5번 비트 설정 */ printf("5번 비트 설정 : "); bitdisp(a); set_bits(a, 0x7, 3); /* 5,4,3번 연속 비트 설정 */ printf("5,4,3번 비트 설정 : "); bitdisp(a); putchar('\n'); invert_bit(a, 5); /* 5번 비트 반전 */ printf("5번 비트 반전 : "); bitdisp(a); invert_bits(a, 0x7, 3); /* 5,4,3번 연속 비트 반전 */ printf("5,4,3번 비트 반전 : "); bitdisp(a); putchar('\n'); b = extract_bits(a, 0x7, 4); /* 6,5,4번 비트를 추출하여 b에 대입 */ printf("6,5,4번 비트 추출 : "); bitdisp(b); return 0; }

   

'Programming > C' 카테고리의 다른 글

The GNU C Library Reference Manual  (0) 2011.09.08
The C Library Reference Guide  (0) 2011.09.08
다시 체계적으로 배우는 C언어 포인터  (0) 2011.07.07
연산자 우선순위  (0) 2010.05.05
매크로  (0) 2010.05.05
Posted by devanix
2011. 7. 7. 22:09

   



C언어포인터
카테고리 컴퓨터/IT > 프로그래밍/언어 > C
지은이 정재은 (정보문화사, 2003년)
상세보기 [ Down ]

   

[ 책소개 ]

이 책은 포인터와 배열만을 다룬것이 아니라 가벼운 인자, 함수포인터, 함수 인자포인터,

자기 참조 구조체등 C언어의 전반에서 모두 사용되는 포인터를 다루고 있다.

메모리해제에 관한 자세한 해설과 예제등 다양한 실무경험을 통해 터득한 내용들을 쉽게 서술하였다

   

[ 목차 ]

Chapter1 포인터의 기초

1 포인터란 무엇인가? 14

2 포인터 변수 15

3 포인터 변수 정의 15

4 쓰레기 주소 값 17

5 & 연산자 18

6 포인터 변수에 번지 할당 20

7 포인터 변수에 왜 타입을 지정하는가? 27

   

Chapter2 1차원 배열과 포인터

1 1차원 배열과 포인터 32

2 첨자 생략 35

3 다차원 배열 35

4 1차원 배열과 포인터 37

5 포인터 + 정수의 의미 39

6 배열명의 숨은 뜻 44

   

Chapter3 2차원 배열과 포인터

1 이것만 알면 만사 OK 50

2 기본 50

3 배열 포인터 정의 52

4 2차원 배열과 2차원 배열 포인터 변수 연결 53

5 2차원 배열 기본 다지기 56

6 imsip = imsi 60

7 int imsi[2][3]의 모든 것 61

8 함수 인자 포인터 65

9 2차원 포인터 다루기 66

10 2차원 포인터 이것만은 알아두자 72

11 int (*imsi)[2], int *temp[2]의 차이 81

12 *temp[3]에서 temp의 의미는? 86

   

Chapter4 문자열과 포인터

1 문자열이란 무엇인가? 92

2 a, 'a', "a"의 차이 92

3 문자열 포인터 변수 94

4 포인터를 이용한 문자열 조작 96

5 착각하기 쉬운 첨자 98

6 *string과 string[ ]의 차이 99

7 문자열 상수 변경 103

8 문자열과 포인터 배열 106

9 포인터 배열에 문자열 할당 109

   

Chapter5 포인터의 포인터

1 포인터의 포인터는 무엇인가? 118

2 포인터의 포인터 변수 정의 118

3 어디에 사용하는가? 118

4 초기화 119

5 포인터의 포인터 참조 121

6 주의 사항 125

7 주의 사항 하나 더 126

8 명령행 인자 127

   

Chapter6 scanf( )와 fgets( )

1 scanf( )와 fgets( ) 132

   

Chapter7 strcpy( )의 비밀

1 strcpy( )의 함정 140

2 배열을 이용한 strcpy( ) 142

3 포인터 변수를 이용한 strcpy( ) 143

4 배열과 malloc( )을 이용한 번지 할당 146

   

Chapter8 뒤죽박죽 포인터

1 뒤죽박죽 포인터? 150

   

Chapter9 포인터의 개념을 깨는 0

1 의문점 154

2 널 포인터 156

3 주의 사항 157

4 널 포인터의 사용처 157

   

Chapter10 바로 알자 getchar( )

1 getchar( )의 함정 162

   

Chapter11 가변 인자

1 가변 인자란? 166

2 가변 인자 사용 단계 167

3 가변 인자를 위한 매크로 168

4 가변 인자의 사용 169

5 주의 사항 171

   

Chapter12 될 것 같으면서 안 되는 코드

1 초보자들이 무시하는 쓰레기 주소 값 174

   

Chapter13 (int *)pointer

1 캐스트 연산자의 이해 186

   

Chapter14 void형 포인터

1 void형 포인터란? 192

2 void형 변수 포인터 정의 193

3 void형 포인터 변수의 성질 193

4 void형 포인터 변수의 사용 193

5 *((int *)voidp)++ 200

6 주의 사항 203

   

Chapter15 함수 인자 포인터

1 함수 인자 포인터란? 206

2 1차원 함수 인자 포인터 206

3 int형 배열 209

4 문자열 포인터 213

5 1차원 포인터 배열 214

6 2차원 포인터 배열 216

   

Chapter16 함수 포인터

1 함수 포인터의 매력 224

2 함수 포인터의 정의 224

3 함수 포인터의 초기화 225

4 함수 포인터 호출 225

   

Chapter17 구조체와 포인터

1 간단한 구조체 개념 230

2 주소록 230

3 구조체 선언과 정의 231

4 구조체 연산 233

5 구조체와 포인터 234

6 멤버 초기화 236

7 주의 사항 237

8 중첩 구조체 240

9 구조체 복사 242

10 매개변수가 구조체 배열인 함수 245

11 자기 참조 구조체 251

12 리스트 262

   

Chapter18 메모리 할당과 해제

1 동적 메모리 할당 270

2 동적 메모리 할당의 장·단점 272

3 malloc( ) 273

4 가장 간단한 메모리 할당 274

5 동적 메모리 영역 초기화 275

6 할당 가능한 메모리 영역 알아보기 276

7 문자열 포인터 변수를 위한 malloc( ) 277

8 구조체 포인터 변수를 위한 malloc( ) 278

9 calloc( ) 279

10 realloc( ) 281

11 메모리 해제 282

12 간단한 메모리 해제 283

13 리스트의 메모리 해제 283

14 복잡한 메모리 해제 287

   

Chapter19 라이브러리

1 라이브러리란? 296

2 라이브러리의 특징 298

3 ar 298

4 ar 옵션 (/usr/ccs/bin) 299

5 라이브러리 생성 단계 299

 

'Programming > C' 카테고리의 다른 글

The GNU C Library Reference Manual  (0) 2011.09.08
The C Library Reference Guide  (0) 2011.09.08
비트 제어 - 설정, 클리어, 반전, 검사, 추출  (0) 2011.07.29
연산자 우선순위  (0) 2010.05.05
매크로  (0) 2010.05.05
Posted by devanix
2010. 5. 5. 17:03


'Programming > C' 카테고리의 다른 글

The GNU C Library Reference Manual  (0) 2011.09.08
The C Library Reference Guide  (0) 2011.09.08
비트 제어 - 설정, 클리어, 반전, 검사, 추출  (0) 2011.07.29
다시 체계적으로 배우는 C언어 포인터  (0) 2011.07.07
매크로  (0) 2010.05.05
Posted by devanix
2010. 5. 5. 16:54

 

 1. 매크로 기본

C언어에서 매크로는 컴파일러가 컴파일을 하기 전에 전처리기에 의해 처리된다. #으로 시작하며 #define, #include 등이 있다.  다음은 주로 많이 사용하는 매크로들이다.

Macro

Description

#define, #undef 매크로 상수나 매크로 함수를 정의(해제) 할 때 사용
#include 파일포함

#ifdef,#ifndef,

#elif,#else,#endif

조건부 컴파일
#pragma 컴파일러나 Linker에게 지시할 때 사용
#line 컴파일할 때 출력하는 Line을 변경한다.
#error 에러를 출력하고 컴파일러를 중지시킨다.

 

2. 매크로 상수와 매크로 함수.

#define 문을 사용하면 매크로 함수와 매크로 상수를 만들수 있다.

#include <stdio.h>

#define MAX 10
#define SQUARE(x) (x)*(x)

void main()
{
    int ar[MAX];                 // int ar[10]
    int s = SQUARE(5);       // int s = (5)*(5)

    printf("s = %d\n", s);
}

 

매크로 함수는 잘못 사용할 경우 버그를 유발할 수 있으므로 조심해야한다.

#include <stdio.h>

#define SQUARE(x) (x)*(x)

void main()
{
    int x = 3;
   
 int s = SQUARE(++x);  // (++x)*(++x)

    printf("s = %d\n", s);     // s = 25
}

위의 경우 프로그래머는 16을 예상하지만 결국 x는 2번증가 되어 25가 나올 것이다.

 

매크로 함수는 모든 형에 적용할 때 사용하는 함수를 만들수 있어 유용하다.

#include <stdio.h>

#define max(a,b) ( (a) > (b) ) ? (a):(b)       // 1

//int max(int a, int b) { return a>b ? a:b;}    // 2

void main()
{
    printf("%d\n", max(5,3) );
    printf("%g\n", max(5.4,3.2) );
}

2번은 int 이외의 값이 전달될 경우, 엉뚱한 결과를 출력할 것이다. 하지만 1번은 모든 type에 대해 제대로 동작할 것이다. (물론 ++ 연산자를 포함한 식이 전달될 경우는 엉뚱한 결과가 나올 것이다.)

 

매크로의 정의가 2줄이상을 경우는 '\'기호를 사용해서 연결해야 한다.

#include <stdio.h>

#define assert(x) if (!(x) ) \
                  {          \
                     printf("assert failed. %s(%d)\n", __FILE__, __LINE__); \
                  }

void main()
{
    int n;
    scanf("%d",&n);
    assert(n);
}

 

3. #, ##을 이용한 매크로 정의

#을 사용하면 해당 심볼을 문자형태로 출력할 수 있다.

#include <stdio.h>

#define dprint(expr) printf(#expr " = %g\n", expr )

void main()
{
    double x = 3.4;
    double y = 2.0;
    dprint(x/y);    // printf("x/y" " = %g\n", expr)
}

위의 예에서 dprint #은 x/y을 "x/y"형의 문자열로 바꾸어 주는 역할을 한다.

 

##은 2개의 Token을 연결하는데 사용한다.

#include <stdio.h>

#define tprint(expr) printf("%d, %d\n", expr##1, expr##2)

void main()
{
    int a1 = 10, a2 = 20;
    tprint(a);

}

##앞의 symbol과 ##뒤의 symbol이 여백없이 연결이 된다.

 

4. 조건부 컴파일 기능

#ifdef, #ifndef, #if, #elif, #else, #endif 등은 조건부 컴파일 기능에 사용된다. 아래 코드를 실행해 보자.

#include <stdio.h>

#define DEBUG     // 주석처리했을 때와 그렇지 않을 때를 비교해 보자.

void main()
{
#ifdef DEBUG
    printf("Debug Message\n");
#endif

    printf("Good-Bye! ^^\n");
}

위 코드는 아래와 같은 방법으로도 사용될 수 있다.

#include <stdio.h>

#define DEBUG

#ifdef DEBUG
    #define TRACE(x) printf(x)
#else
    #define TRACE(x)
#endif

void main()
{
    TRACE("Debug Message\n");
    printf("Good-Bye! ^^\n");
}

또한 아래와 같이 System에 따라 다른 헤더를 포함시킬때도 사용할 수 있다.

#if SYSTEM == WINNT
    #define HDR "winnt.h"

#elif SYSTEM == LINUX
    #define HDR "linux.h"

#elif SYSTEM == MAC
    #define HDR "mac.h"

#endif

#include HDR

 

5. Conditional Inclusion

프로그램을 만들때 여러개의 헤더와 소스 파일을 사용하다 보면 특정 헤더파일이 2번 include되는 경우가 발생할 수 있다. 이 경우 컴파일시에 문제가 발생할 수 있다.

/* hdr.h */

struct pepople
{
    char name[256];
    int  age;
};

/* xxx.c */

#include "hdr.h"
#include "hdr.h"

void main()
{

}

위의 경우 강제로 2번 include 했지만 실제 작업중에는 피치 못하게 2번 include하게 되는 일이 발생할 수 있다. 이때 헤더 파일이 1번만 include되게 하려면 다음과 같이 하면된다.

/* hdr.h */

#if !defined(HDR) // #ifndef HDR 과 동일

#define HDR

struct pepople
{
    char name[256];
    int  age;
};

#endif /* HDR */

/* xxx.c */

#include "hdr.h"
#include "hdr.h"

void main()
{

}

모든 헤더파일에는 위와 같은 매크로를 넣어주는 것이 일반적이다.

 

6. 미리 정의된 매크로

C 에는 사용자가 정의 하지 않더라도 미리정의되어 있는 매크로 상수가 몇가지 있다.

Predefine Macro

Description

__FILE__

현재 컴파일되는 파일의 이름

__LINE__

현재 컴파일되는 소스의 Line No.

__DATE__

현재 날짜

__STDC__

현재 컴파일러가 ANSI 표준을 따를 경우 1로 정의 된다.

__TIME__

시간

__TIMESTAMP__

 
아래 코드를 보자.

#include <stdio.h>

void main()
{
    printf("%s\n", __FILE__);
    printf("%d\n", __LINE__);
    printf("%s\n", __DATE__);
    printf("%s\n", __TIME__);
    printf("%d\n", __TIMESTAMP__);
}

 

7. #pragma

#pragma 매크로는 컴파일러나 Linker에게 어떤 지시를 하기 위해 사용한다.

     #pragma 지시어

형식으로 사용된다. 지시어의 종류는 컴파일러 다르지만 vc++에서 사용되는 지시어는 대략 아래와 같은 것들이 있다.

alloc_text auto_inline bss_seg check_stack
code_seg comment component conform
const_seg data_seg deprecated function
hdrstop include_alias init_seg1 inline_depth
inline_recursion intrinsic managed message
once optimize pack pointers_to_members1
pop_macro push_macro runtime_checks section
setlocale unmanaged vtordisp1 warning
message 라는 지시어를 사용하면 컴파일중 Output 창에 메시지를 출력하는 것이 가능하다.

void main()
{

#pragma message("이 메세지 컴파일러가 컴파일하는 중에 출력창에 출력됩니다.")

}

# 매크로와 #pragma, __FILE__, __LINE__ 등을 응용하면 아래와 같이 유용한 매크로를 정의해서 사용할 수 있다.

#define TOSTR(x)    #x
#define STR(x)      TOSTR(x)
#define MSG(desc)   message(__FILE__"("STR(__LINE__)"):"#desc)

void main()
{
    int x = 10;
    int y = 20;

#pragma MSG(이 코드는 나중에 다시 살펴볼 필요가 있습니다)  // A

    x = y / 2;

    ......;
    ......;
}

위의 A처럼 코드를 만들어 둘 경우 매번 컴파일 할 때마다 메시지를 볼수 있을 것이다.
프로그램이 길어지고 나중에 변경할 필요가 있을 때 잊지 않고 작업을 할 수 있을 것이다.

 

8. #line, #error

#line매크로는 컴파일러가 출력하는 현재 line count를 변경하는 매크로 이다. 자주 사용되지는 않는다.

void main()
{
#line 100

    int x = 10      // error ;를 빼 먹었다.
}

위 코드를 컴파일 하면 ;이 빠져서 에러가 날것이다. 그런데 101번째 line이라고 나오게 될것이다.

 

#error 매크로는 컴파일을 멈추고 에러를 출력하게 하는 매크로 이다.

// #define LINUX

void main()
{
#ifndef LINUX
    #error this os is not linux
#endif
}

Posted by devanix