sizeof 연산자


sizeof A  : A 메모리의 크기를 

바이트 단위로 알려준다.


cpu 하는 연산이 아닌 

컴파일러가 하는 연산.


컴파일러가 기계어로 

번역하는 과정에서 발생하는 연산.


자료형의 크기를 컴파일러에게 물어보는 .


  

 

int Data = 10;

printf("%d\n", sizeof(Data));

 

변수 Data의 자료형은 int이므로 

4를 출력

 


printf("%d\n"sizeof(char*));

 

32비트 어플리케이션 VS 사용하고 있다면 

char 대한 포인터이므로 

4 출력



char Name[16] = { "Start" };

printf("%d\n", sizeof(Name));

 

배열의 이름인 

Name 자료형은 char이고

결국 char[16] 같으므로 

16 출력

 

 

char Name[16] = { "Start" };

printf("%d\n", sizeof(Name + 1));

 

"char[] == char*"

"[] = *" 로 변환 될 수 있다.


"char*" 본질은 주소이므로 

여기에 정수(int)'1'을 더하면 연산결과는 

다시 주소를 담을 있는 포인터가 된다.

따라서 4 출력


(포인터에 대해 아직 잘 몰라서 일단 들은대로 적음)

(나중에 제대로 이해하면 첫번째 문단의 이유를 다시 제대로 적겠습니다)


 

int Data = 10;

printf("%d\n", sizeof(++Data));

printf("%d\n", Data);

 

sizeof연산은 컴파일러가 하는 연산.

단항증감에 대한 연산을 수행하지 않고

자료형이 무엇인가를 알려주는 것.


따라서 Data변수의 자료형은 int이므로

4 출력하게 된다.


다음행에 변수 Data 정보를 출력해보면

원래 Data 값인 10 출력된다.






** 잘못알고 있는 것이 있으면 댓글로 알려주시면 감사하겠습니다! **

'프로그래밍 > C언어' 카테고리의 다른 글

쇼트서킷(Short-circuit)  (0) 2018.07.02
단항 증감 연산자  (0) 2018.06.28
단순 대입 연산자  (0) 2018.06.28
비트연산자  (0) 2018.06.28
자료형, 보수와 음수표현  (0) 2018.06.14

관계 연산자

A == B : AB가 같으면 참(1)

A != B : AB가 다르면 참(1)

 


논리 연산자

A && B : AB 모두 참일 경우 참(1). 논리곱

A || B : AB 둘 중 하나가 참이면 참(1). 논리합

!A : A의 결과를 참이면 거짓으로

 거짓이면 참으로 반전시킨다.

 


쇼트서킷(Short-circuit)


논리합의 경우 둘 중 하나면 참이다.

따라서 왼쪽항이 참이면 

오른쪽항은 검사하지 않아도

논리합의 전체 결과는 참이다


하지만 논리곱에서는 

왼쪽항이 참인 경우에만

오른쪽항의 연산을 수행한다.

반대로 왼쪽항이 거짓이라면 

오른쪽항을 검사하지 않아도

전체결과는 거짓이 된다.


이 같은 특징으로 

논리연산자와 조합된 다른 연산식이나

조건식이 생략되는 경우를 쇼트서킷이라 한다.

불필요한 연산이 줄어들면 

프로그램의 효율이 그만큼 높아진다.

논리 연산은 무조건 왼쪽부터 시작


 

int k, x = -1, y = -1, z = 1;

k = ++x || ++y && ++z;

printf("%d %d %d %d\n", k, x, y, z); 

 

++x의 연산을 수행해서 x의 값이 0으로 변경.

‘||’연산은 논리합인 논리식이므로

두번째 항을 연산.


++y연산을 수행해서 y의 값이 0으로 변경.


‘&&’연산은 논리곱인 논리식이므로

왼쪽항이 거짓이면 

오른쪽항은 연산을 수행하지 않는다.


따라서 ++z는 수행하지 않게 되고 

값은 1에서 변하지 않는다.


‘||’연산에서 

왼쪽항 오른쪽항 모두 거짓이므로

k에 저장되는 값은 0이 된다.

따라서 0, 0, 0, 1이 출력.



int k, x = -1, y = -1, z = 1;

k = x++ || ++y && ++z;

printf("%d %d %d %d\n", k, x, y, z);


x++연산은 행의 가장 마지막에 연산을 하므로

x의 값인 -1‘||’연산을 따지게 된다

-1의 값은 참이고 ‘||’은 논리식이 논리합이므로

왼쪽항이 참이면 다음 항은 

계산을 하지 않아도 참이므로 

++y, ++z연산은 수행하지 않는다


따라서 k의 값은 참이 되고 값은 1이 된다.

따라서 1, 0, -1, 1이 출력.






** 잘못알고 있는 것이 있으면 댓글로 알려주시면 감사하겠습니다! **

'프로그래밍 > C언어' 카테고리의 다른 글

sizeof 연산자  (0) 2018.07.02
단항 증감 연산자  (0) 2018.06.28
단순 대입 연산자  (0) 2018.06.28
비트연산자  (0) 2018.06.28
자료형, 보수와 음수표현  (0) 2018.06.14

단항 증감 연산자


1 값이 증가하거나 감소

단항 연산자가 왼쪽에 붙으면 전위(++A)

단항 연산자가 오른쪽에 붙으면 후위(A++)

전위식은 우선순위가 높으며

후위식은 우선순위가 아주 낮다.

 


++A, A++ 은

 

A += 1 또는, 

A = A + 1 로



--A, A-- 은


A -= 1 또는, 

A = A – 1 


로 설명할 수 있다.


 

int A = 0;

printf("%d\n", ++A);

 

변수 A1의 값을 더하고 

그 값을 출력한다

1의 값이 출력된다.

       


int A = 0;

printf("%d\n", A++);

printf("%d\n", A);

 

변수 A의 초기값을 먼저 출력하고

맨 마지막에 1의 값을 더하여

변수 A에 저장한다.

따라서 01을 출력.


이처럼 후위식은 해당 행의 연산이 끝나고

맨 마지막에 값의 증가가 이루어진다.






** 잘못알고 있는 것이 있으면 댓글로 알려주시면 감사하겠습니다! **

'프로그래밍 > C언어' 카테고리의 다른 글

sizeof 연산자  (0) 2018.07.02
쇼트서킷(Short-circuit)  (0) 2018.07.02
단순 대입 연산자  (0) 2018.06.28
비트연산자  (0) 2018.06.28
자료형, 보수와 음수표현  (0) 2018.06.14

단순 대입 연산자


A = B

B 혹은 B 들어있는 값을 A 저장

메모리에 정보를 저장하는 .

기존에 저장된 값이 있다면 덮어쓰기가 됨.

대입 연산자의 왼쪽 : l-value(A)

오른쪽 피연산자 : r-value(B)

메모리의 쓰기가 일어남

l-value는 반드시 메모리일 .

 

 

ex) int A = 0;

        A = 3;

 

변수를 선언할 A 0으로 초기화.

그리고 변수 A 정수 3 대입하는 의미.

기존에 있던 0 정보는 지워지고

3 정보로 변경되어 저장됨.    

 

int A = 0 에서의

‘=’ 단순대입연산자가 아니라

변수 선언할 때의 문법상 필요에 의한 .

    비슷한 예로 ‘*’ 곱셈 연산자이지만

변수를 선언할 때는 포인터를 의미.

 



오류 코드들


1) 3 = 4;


정수형 상수 3 상수 4 저장할  없음.

l-value에는 메모리가 위치해야 .

상수는 쓰기가 허용되지 않고

또한 값을 저장할 있는 메모리도 아니다.

 


2) char Name[8];

       Name = 1;


배열의 본질은 주소이고

그 주소는 상수.

따라서 상수에는 값을 저장할 없다.

 

 

3) const : 한정어, 읽기전용화, 상수화


const int Data = 10;

Data = 20;

 

const 선언하면 해당 변수는

정보의 읽기만 있고

다른 정보를 저장할 없게 된다.

변수의 상수화가 .

10 = 20; 이라는 결과를

초래하기 때문에 오류가 발생.

 

int A = 0;

const int Data = 10;

A = Data;

 

변수 Data 상수화 하였지만

데이터의 읽기는 가능하므로

위와 같은 코드는 오류가 아니다.

변수 A 10 정보가 저장됨.

 

 

const 사용하는 이유는

메모리의 확보도 하고

정보의 훼손을 방지하기 위함.






** 잘못알고 있는 것이 있으면 댓글로 알려주시면 감사하겠습니다! **

'프로그래밍 > C언어' 카테고리의 다른 글

쇼트서킷(Short-circuit)  (0) 2018.07.02
단항 증감 연산자  (0) 2018.06.28
비트연산자  (0) 2018.06.28
자료형, 보수와 음수표현  (0) 2018.06.14
형식 문자열 입출력 함수 ( 스캔셋 ) (3)  (0) 2018.06.07

비트연산자


비트 단위의 정보를 다룰 있는 연산자.

시스템 자체나 네트워크 관련된 프로그램 개발할 사용

특정 위치의 비트가 참인지 거짓인지 확인하거나

값을 변경할 경우에 사용함.

쉬프트연산은 패딩을 동반.

원하는 비트만큼 쉬프트하고 데이터가

기존비트의 크기를 유지해야 한다면 

유실된 비트의 수만큼 새로운 정보가 채워지는데 

이것을 패딩이라 한다.

왼쪽으로 쉬프트를 통해 곱셉 연산을

오른쪽 쉬프트를 통해 나눗셈 연산을 

수행한 결과를 얻을 있음.

 

 

AND : & (값이 모두 1 )

ex) 0x11223344 & 0xFFFF0000 : 11220000

0001 0001 0010 0010 0011 0011 0100 0100

1111 1111 1111 1111 0000 0000 0000 0000

0001 0001 0010 0010 0000 0000 0000 0000

 

OR : | (값이 하나라도 1이라면

ex) 0x11223344 | 0xFFFF0000 : FFFF3344

0001 0001 0010 0010 0011 0011 0100 0100

1111 1111 1111 1111 0000 0000 0000 0000

1111 1111 1111 1111 0011 0011 0100 0100

 

XOR : ^ (값이 서로 다른 경우에 )

ex) 0x11223344 | 0xFFFF0000 : EEDD3344

0001 0001 0010 0010 0011 0011 0100 0100

1111 1111 1111 1111 0000 0000 0000 0000

1110 1110 1101 1101 0011 0011 0100 0100

 

NOT : ~ (값을 반전)

ex) ~0x11223344 : EEDDCCBB

0001 0001 0010 0010 0011 0011 0100 0100

1110 1110 1101 1101 1100 1100 1011 1011

 


<< : 왼쪽으로 쉬프트

ex) 0x00001122 << 8 : 0x00112200

0000 0000 0000 0000 0001 0001 0010 0010

0000 0000 0001 0001 0010 0010 0000 0000


8비트를 왼쪽으로 쉬프트하고 

왼쪽으로 쉬프트 값은 절사되고

오른쪽에 새로 값이 패딩되는데 

값은 0으로 채워진다.

 


>> : 오른쪽으로 쉬프트

ex) 0x00001122 >> 8 : 0x00000011

0000 0000 0000 0000 0001 0001 0010 0010

0000 0000 0000 0000 0000 0000 0001 0001 


8비트를 오른쪽으로 쉬프트하는데

원래 수가 양수이면 0, 음수였으면 1

패딩하는 것이 왼쪽으로 쉬프트와 다른점.

 

-8 >> 3 예를 들어보면

1111 1111 1111 1111 1111 1111 1111 1000

1111 1111 1111 1111 1111 1111 1111 1111



-8을 오른쪽으로 3만큼 쉬프트 하게되면

2 2승까지의 0 정보가 절사되게 되고

-8은 음수이고 부호비트가 1이므로

그 부호를 유지하기 위해서

왼쪽비트부터 1로 채워지게 된다.






** 잘못알고 있는 것이 있으면 댓글로 알려주시면 감사하겠습니다! **

자료형

일정 길이(byte 단위의 크기) 메모리에 

저장된 정보를 해석하는 방법


상수 : 정해진 , 변화가 없음.

변수 : 변하는 , 정해지지 않은

   변수의 선언은 메모리의 확보를 의미함.

 

정수형(고정소수점) : 1234.0, 100.0 같이 

소수점이 고정되어 있음.(실제는 정수만 표현)


char(1byte)

short(2byte)

int(4byte), long(4byte),

long long int(8byte)

 

실수형(부동소수점) : 1.234, 12.34, 123.4 같이 

소수점의 위치가 변화.


float((4byte)

double(8byte)


float 경우 소수점 이하 표현이 6자리를 넘어가면 

자료의 신뢰성이 떨어진다.

그러므로 실수형을 사용할 경우 

소수점 15자리까지 유효한 double형을 사용한다.

 



보수와 음수표현


컴퓨터는 보수를 사용하여 음수를 표현하고

보수를 사용하여 뺄셈을 한다.


2진수 0011 10진수 '3'이다.

맨 왼쪽부터 10진수 8,4,2,1로 계산되고

2+1을 하면 3이 된다.

처음에 음수를 표현할 때는

왼쪽 비트를 1 표시하면 음수,

0으로 표시하면 양수로 표현되었는데


그렇다면 위의 2진수 0011 

왼쪽 비트를 1 바꾸면 1011이 되고

수가 '-3'으로 표현되었던 것이다

하지만 방식은 현재 사용하지 않는다.


왜냐하면 이런 경우 0 수를 

표현할 경우 2진수 0000 +0,

1000 -0이라는 숫자로 표현되게 되어 

경우의 수가 낭비되어 컴퓨터는 많은 수를 

표현하기 위해서 2 보수를 사용한다.


2의보수를 구하는 방법은

1 보수에 1 값을 더하면 

2 보수를 구할 있다.

1 보수는 0 1로, 1은 0으로 바꾸면 된다.


그래서 2진수 0011 2 보수를 구해보면

먼저 1 보수를 구하면 되는데

0 1로, 1은 0으로 바꾸면

2진수 1100 되고 여기에 1 값을 더하면

2의 보수가 되는 것이다.


그러면 2진수 1101 되고 값이

10진수 3 2 보수가 된다.


실제로 0011(3)의 값과

1101(-3)의 값을 서로 더해보면 

0 되는 것을 있다.

계산 마지막 5째 자리1은 

자리범위를 초과하므로 버려지게 된다.

 

여기서 중요한 것은 2진수 1101 

부호가 있는 자료형(signed)으로 보면

-3으로 해석될 있지만


부호가 없는 자료형(unsigned) 본다면 

13 수로 해석될 있다.


2진수 1101 계산해보면 

8+4+1 = 13이기 때문이다.


따라서 값의 정보는 하나지만

이 정보를 어떻게 해석하느냐에 따라서 

값이 다르게 해석될 수 있다.






** 잘못알고 있는 것이 있으면 댓글로 알려주시면 감사하겠습니다! **

스캔셋 "%[]"

scanf함수의 형식문자를 입력하는 위치에 

위와 같은 형식을 이용하면 원하는 결과값을

변수에 저장할 수 있다.

해당하는 값을 변수에 저장하고

남은 정보는 버퍼에 그대로 남아있다.



scanf(“%[A-Z]”, 식별자);  "TESTstring" 입력

변수에 "TEST" 저장하고 버퍼안에 "string" 남아있음.

대문자 A에서 Z까지의 정보를 변수에 저장.

출력함수를 사용하면 "TEST"출력.

 

scanf(“%[A-Z,a-z]”, 식별자);  "TESTstring" 입력

"TESTstring"이 변수에 저장된다.

대문자와 소문자 정보 모두를 변수에 저장.

버퍼에는 개행문자가 남아있음.

출력함수를 사용하면 "TESTstring"출력.

 

scanf(“%[ ,A-Z,a-z]”, 식별자);  “ TEST string”입력

" TEST string"이 변수에 저장

마찬가지로 버퍼에 개행문자가 남이있음.

A-Z앞에 스페이스를 입력하였으므로 

스페이스의 문자 정보도 변수에 저장한다.

대문자 소문자 그리고 

스페이스 문자도 변수에 저장.

출력함수를 사용하면 TEST string"을 출력

 

scanf(“%[^A-Z]”, 식별자);  “ testString” 입력

“ test”이 변수에 저장. 버퍼안에 “String” 남음.

대문자 A~Z까지 제외하고 다 저장하는데

빈칸과 test까지 변수에 저장하고

다음에 대문자 S나오니

뒤로는 그냥 버퍼에 저장.

출력함수를 사용하면 " test"을 출력

 

scanf(“%[^\n]%*c”, 식별자); 

개행문자를 제외하고 나머지는 전부

변수에 저장하라는 뜻인데

%*c가 버퍼에 남은 한 문자를 제거하는 것이므로

gets함수와 같이 모든 문자열을 다 출력가능.

버퍼에 남는 문자가 없게 된다.






** 잘못알고 있는 것이 있으면 댓글로 알려주시면 감사하겠습니다! **

scanf: getcahr, gets함수와 마찬가지로 I/O buffer 사용.

       scanf 사용자가 입력한 문자를 형식문자에 따라

       인자의 주소에 저장하고 숫자, 문자, 문자열을 입력받음.

       현재 scanf함수는 gets함수와 마찬가지로

보안결함이 있으므로 scanf_s 사용(VS에서만)

 


int Date = 0;

scanf_s(“%d”, &Date);

 

Date라는 이름의 변수를 int 선언. 값은 0 초기화

&Date: 이름이 Date 변수의 메모리의 주소

scanf함수가 호출되어 사용자가 숫자 605 입력했다면

버퍼에 문자 6,0,5 저장이 되고

%d형식에 의해서 문자 6,0,5 정수형식으로 해석되어

정수 605 Date라는 식별자의 주소에 저장된다.       

 

&Date 말고 Date 쓰면 어떻게 될까?

실행시키고 값을 입력하면 오류가 발생한.

scanf함수에서 &Date 의미하는 것은

변수 Date 주소를 뜻하고

주소에 사용자가 입력한 값을 저장한다는 것인데

& 떼고 Date만을 입력하게 되면

현재 변수 Date 값은 0으로 초기화되어 있는 상태이고

의미는 0 해당하는 메모리의 주소에

사용자가 입력한 데이터를 덮어쓰기를 하라는 뜻이 되고

주소들은 운영체제가 쓰고 있는 영역이라 오류가 발생하게 된다.


 

scanf_s(“%d, %d”, &a, &b);

printf함수와 마찬가지로 형식문자의 구분을 

, 하는 경우 에러가 발생

scanf함수는 형식문자를 여러 작성할 경우

형식문자 사이의 입력을 구분한다.

위의 같이 형식문자 사이에 , 입력하는 경우

10 20 출력하고자 한다면

정수 10 20만을 입력하면 되는 것이 아니고

정수 10 입력하고 , 반드시 포함시켜야 정상 출력된다

1. 10, 20 이나 2. 10,엔터 20 이런식으로.

따라서 scanf함수의 경우 형식문자 사이에

따로 구분자를 쓰지 않고 붙여서 작성하면 된다.

 

 

만약 scanf함수로 정수를 입력받고

gets함수로 다시 문자를 입력 받으려는 경우

gets함수 특성상 I/O buffer하며

문자열을 입력받는 함수이므로

앞의 scanf함수에서 정수를 입력할 때

정수를 입력하고 엔터를 치면 엔터(개행문자)가

정수와 함께 버퍼에 남게되고 

마지막에는 버퍼에 개행문자만 남게 된다.

그러므로 사용자에게 따로 입력받지 않게 되며

버퍼에 있는 개행문자가 입력되고

원하는 문자를 입력하지 못한채 실행창이 종료되거나

입력되지 않은 값이 그대로 출력되게 된다.

 

예를 들어 scanf함수로 정수를 입력받을

10 입력했다면 1,0,\n 버퍼에 남아있고

scanf 형식문자 %d 문자 1,0 뽑아서

정수형식으로 변수에 저장하고 \n 그대로

버퍼안에 남아있어 다음 입력을 받을

gets함수는 버퍼안에 남아있는 \n

입력데이터로 인식하게 되는 결과가 발생한다.

그래서 문자를 출력하는 함수를 사용할 때는

버퍼의 개행문자까지 신경써야 하겠다.



%*c : 이 명령어는 형식문자는 형식문자대로 

역할을 수행하고  뒤에 남은 글자는 제거라는 뜻.


) scanf_s(“%d%*c”, &변수);

이렇게 하면 %d형식문자에 의해서

사용자가 입력한 숫자를 정수형으로 해석해

변수에 저장하고 남은 개행문자는 버퍼에서 제거한다.

 

다른 방식으로 scanf함수는 그대로 사용하고

다음줄에 getchar();로도 가능

남은 개행문자를 getchar함수에 의해서 입력받음.


예) scnaf_s("%d", &변수);

getchar();


 

scanf_s함수 %s, %c 사용법


변수를 0초기화한다

scanf_s(“%c”, &식별자, sizeof(식별자));


변수를 배열로 선언한다

scanf_s(“%s”, 식별자, sizeof(식별자));




** 잘못알고 있는 것이 있으면 댓글로 알려주시면 감사하겠습니다! **

printf : 형식문자열을 사용하여 문자열을 출력하는 함수

         형식문자를 구분하기 위해 %기호를 사용

         형식문자의 개수에 따라 인자의 수도 일치해야

         특정 숫자에 대응하는 문자를 만들었는데 아스키코드라 한다

         컴퓨터는 문자를 모르지만 해당 숫자에 대응하는 아스키코드에 의해서

         문자나 특수문자를 표현할 있다.

 


 형식문자

자 료 형 

설     명 

 %c

 int(char) 

 아스키 문자로 출력

 %d

 int

 부호가 있는 10진수로 출력

 %u

 unsigned int

 부호가 없는 10진수로 출력

 %x

 모든 자료형

 16진수로 출력

 %e

 float, double

 지수형 실수로 출력

 %f

 float, double

 10진수 실수로 출력

 %p

 pointer

 16진수 주소로 출력

 %s

 string 

 인자가 가리키는 메모리 값의 문자열로 출력


  

printf(“%c”, 65);

형식문자 %c 인자의 값을 정해진 값에 맞는

아스키코드로 출력해주는데 숫자 65

해당하는 문자는 A이므로 문자 A 출력.


 

printf(“%c”, 65+1);

숫자 65 해당하는 아스키코드가 A이고

숫자 66 해당하는 아스키코드가 B이므로

65+1 66이므로 문자 B 출력.


 

printf(“%d”, 65);

형식문자 %d 인자의 값을 부호가 있는 10진수로 출력하므로

숫자 65 출력.


 

printf(“0x%x”, 65);

형식문자 %x 인자의 값을 16진수로 출력하며

16진수 문자인 것을 알기위해 형식문자 앞에 0x를 작성

0x41 출력.

 


printf(“%s”, “Hi”);

형식문자 %s 인자가 가리키는 메모리 값의 문자열을 출력하므로

대응하는 인자의 메모리 값의 문자열인 Hi 출력.


char Name[8] = {"Hi"};

printf("%s", Name);

위와 똑같은 결과를 출력



char Name[12] = {“Hello”};

printf(“%p”, Name);

 

형식문자 %p는 인자의 16진수 주소를 출력하는 것이고

Name이라는 식별자는 “Hello”라는 문자가

저장되어 있는 16진수 주소를 가지고 있는 

배열 이름이고 그 주소를 출력하는데 쓰인다.


 

printf(“%f”, 123.45);

형식문자 %f 인자의 값을 10진수 실수로 표현하며,

%f 32비트, %lf 64비트 자료형이지만

printf함수에서는 float double

모두 %f 표현해도 문제가 되지 않는다

double 표현되므로 123.4500000으로 출력.

컴파일러에서 기본값으로 지정한 소수점 이하 자리수가

6자리이기 때문에 소수점 이하 6자리까지 표현됨.

 

기본적으로 실수의 값을 double형식으로 인지.

123.45라고 한다면 double형식으로 표현.

만약 값을 123.45f 작성하면 해당 자료형을

float형식으로 표현한다.

값은 123.449997 나온다.

 

여기서 주의할 점이 바로 유효자리수 인데

유효자리수가 의미하는 것은 신뢰할 있는 값의 범위이다.

float형의 경우 소수점이하 7번째 자리부터의 

값은 잘못된 값이라는 뜻이고 이를 부동소수점 오차라고 한다.

float형의 유효자리수 6

double형의 유효자리수 15

 

따라서 float 소수점이하 6자리까지의 값은 신뢰가능하지만

이하 자리의 값은 반올림하여 표현하므로

표현 값의 범위가 넓은 실수를 계산하는 것에는

정확성이 떨어지므로 float 왠만하면 쓰지 않는 것이 좋다.

 

 

printf(“%12.3f”, 123.45)

전체 자리수 12자리에 소수점 아래 3자리까지 표현

    123.450” 이런식

"     123"까지가 8자리, "450"까지 3자리. 


 

printf(“%.10f”, 123.45)

소수점 아래 10까지 표현. 123.4500000000


 

printf(“%d”, 123.45)

실수 값을 정수표현방식으로 출력하는 %d 작성하면

출력값의 오류가 발생

 


printf(“%f”, 123)

정수 값을 실수표현방식으로 출력하는 %f 작성하면

출력값의 오류가 발생



printf(“%d”, -1) : -1


printf(“%u”, -1) : 4,294,967,295

32비트가 표현할 있는 최대값






** 잘못알고 있는 것이 있으면 댓글로 알려주시면 감사하겠습니다! **

gets / puts

gets : 사용자로부터 문자열을 입력받아 

함수의 인자로 명시한 주소의 메모리에 저장한다.

getchar함수와 같은 점은 입출력버퍼가 비어있는지 확인하고 

비어있다면 문자 혹은 문자열을 입력받아 입출력버퍼에 저장한다는 점이고, 

다른 점은 문자 하나씩 반환하는 것이 아니라 문자열을 한꺼번에 반환한다.

 

puts : 문자열을 모니터 화면(콘솔)에 출력하는 함수.

puts함수는 출력할 문자열의 길이를 따로 명시하지 않아도 

알아서 출력하는데 C언어에서 모든 문자열은 null(0)로 끝나기 때문에 

'0'이 나올때까지 출력하는 것이다.

 


char Name[5];

gets(Name);

puts(Name);

 

이 코드는 char형의 자료형 5개를 확보하라는 배열 선언이다.

이 선언에서 Name는 배열을 대표하는 이름이며 

그 실체는 연속된 메모리 시작의 주소이며 식별자라고 부른다.

char형인 자료형5개 확보되었으므로 5바이트의 메모리가 확보되며,

gets함수는 버퍼에 메모리가 비었는지 확인하고 비었으면 사용자의 입력을 기다린다.

‘TEST’라고 입력하면 Name라는 식별자의 메모리 시작의 주소부터

차례대로 문자가 저장되고 반환하게 된다.

그리고 puts함수는 gets함수가 반환한 문자열인 ‘TEST’를 콘솔화면에 출력하게 된다.




* 참고 *


비주얼스튜디오(VS)에서는 gets함수는 (C언어 자체에서 가지고 있는 결함

보안에 결함이 있으므로 gets_s를 사용하는 것을 권하고 있다.

 


char Name[4];

gets_s(Name, sizeof(Name));


2번째 매개변수에 sizeof연산자를 적어준다

sizeof연산자는 지정한 대상의 메모리 주소를 표시한다.

소스 실행결과 Name이라는 식별자가 가진 자료형이 몇 바이트인지 계산한다.

char형의 자료형은 1바이트인데 4개의 배열을 가지고 있으므로 총 4바이트이다.

그러므로 gets_s(Name, 4); 라고도 작성할 수 있다.

하지만 왠만하면 sizeof라는 연산자를 사용하도록 하는 것을 권장.

 

 

* 버퍼오버플로우(Buffer overflow)에 의한 버퍼오버런(Buffer overrun)

 

 

위 코드로 예를 들면 자료형이 char형인 식별자 Name은 

4바이트의 메모리 공간을 확보했는데 만약에 4글자 이상을 입력하게 되면? 

4글자 이상을 입력하고 엔터를 누르면 VS에서 실행 오류가 발생한다.

배열 관련 설명에서 기술했듯이 

C언어에서는 문자열의 마지막은 항상 null(0)로 끝나는데 

4바이트의 메모리 공간은 3개의 문자와 null문자로 끝나기 때문에 

확보한 4바이트 메모리 공간의 저장 허용범위를 초과하게 되는 것이다.


하지만 이 gets함수는 배열선언으로 확보한 메모리의 크기만큼만 제한해서

사용자에게 문자열을 입력받는 것이 아니라

사용자가 문자열을 입력하는 대로 그대로를 제한 없이 받기 때문에 

이러한 오류가 발생한다

그래서 C언어에서는 메모리 관리를 본인이 해야하고 

그만큼 코드 작성시 이에 관해서 보다 깊이 생각해봐야겠다.





** 잘못알고 있는 것이 있으면 댓글로 알려주시면 감사하겠습니다! **

+ Recent posts