일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- half adder
- Linked List
- Algorithm
- uart 통신
- gpio
- verilog
- stop watch
- LED
- ring counter
- Pspice
- Recursion
- DHT11
- FND
- dataflow modeling
- test bench
- KEYPAD
- soc 설계
- pwm
- BASYS3
- i2c 통신
- java
- vivado
- Edge Detector
- behavioral modeling
- ATMEGA128A
- structural modeling
- hc-sr04
- atmega 128a
- D Flip Flop
- prescaling
- Today
- Total
거북이처럼 천천히
C언어 잡다한 정보 정리 (1) 본문
1. 서로 다른 자료형으로 연산하게 되면 메모리의 크기가 큰 자료형을 따라 결과값이 나오게 된다.
문제) 아래와 같이 서로 다른 자료형인 int와 double을 가지고 연산하게 된다면 연산한 결과는 어떤 자료형을 갖게 되는가?
int a = 20;
double b = 5.5;
// a / b == 연산 결과 : double형으로 출력
정답) int형은 4 byte, double형은 8 byte이고, 8 byte가 4 byte보다 크기 때문에 a / b의 연산 결과는 double 형을 갖는다.
이는 '자동 형 변환'에 의해 발생된다. 자동 형 변환에 의해 int / double을 연산이 이루어지면 int형을 double형으로 자동적으로 형 변환이 발생하여 double / double 형태로 연산을 하여 출력값이 double 형으로 리턴하게 된다.
2. Shallow copy
와 Deep copy
문제) 원소들을 다른 배열에 복사할 경우에는 Shallow copy 방법과 Deep copy 방법 중을 이용해야 하는가?
정답) 배열명은 배열의 첫 번째 원소의 주소값을 가르키는 주소 상수이다. Shallow copy에 사용되는 대입 연산자 경우
에는 왼쪽에는 l-value가 와야 하는데, 배열명은 데이터 값을 저장할 수 없는 상수(r-value)이기 때문에 배열을 초기
화하는 과정을 제외하면 배열을 복사하기 위해서 Deep copy 방법을 사용해야 한다.
따라서 대입 연산자를 사용하기 전, 대입하고자 하는 곳이 값을 저장할 수 있는 l-value인지 확인하고 사용해야 한다.
3. Input Buffer를 클리어 하는 방법
표준 입력 함수를 사용하여 문자 , 문자열을 받는 과정에서 Buffer에 남아 있는 데이터 값들에 의해 의도치 못한 입력이 변수에 저장되는 상황을 자주 접할 수 있기 때문에 문자, 문자ㅁ열을 입력받는 과정에서 주의할 필요가 있다.
그래서 이러한 상황을 피하기 위해 Input Buffer를 의도적으로 비우는 작업을 이용할 수 있는데, 이때 사용할 수 있는 방법에는 크게 3개의 방법이 있다.
- getchar() 함수를 이용하여 입력 버퍼 비우기
- 다음과 같이 while문 과 getchar() 함수를 이용하여 입력 버퍼 비우기
while(getchar() != NULL);
- rewind(stdin) 함수를 이용하여 한 번에 입력 버퍼를 비울 수 있다.
4. scanf 함수의 보안 취약성 문제
scanf 함수는 보안에 취약하다는 문제점에 의해 더 이상 지원을 하지 않으며, 이를 보완한 표준 입력 함수인 scanf_s 함수를 이용할 수 있다.
문제) scanf 함수가 어떤 부분에서 보안 부분에 취약성을 갖고 있는가?
정답) 예를 들어 scanf 함수를 통해 문자열을 입력받고자 하는 상황이다. 이 과정에서 문자열을 입력 받기 위해 길이 10인
char형 배열을 이용하여 받고자 했는데, 실제로 scanf 함수를 통해 들어온 문자열의 길이는 문자열의 길이가 9보다
큰 문자열이 들어 왔다. 그럼 이 경우에는 메모리에 어떤 형태로 데이터가 저장되는가?
아래와 같이 입력된 데이터를 모두 저장하기 위해 길이가 10인 배열의 한정적인 메모리 공간을 넘어 다음 메모리
영역까지 넘어가 Overwrite (= Overflow) 한 것을 확인 할 수 있다.
#include <stdio.h>
int main(void) {
char data[10] = { 0, };
printf("문자열을 입력하시오 : ");
scanf("%s", data, sizeof(data));
printf("data = %s\n", data);
return 0;
}
그래서 만약 overwriter 된 메모리 영역이 보안과 밀접한 데이터일 경우, 데이터가 훼손되면서 보안 시스템에 심각한
문제를 발생시킬 수 있기 때문에 더 이상 최신 버전에서는 scanf 함수를 지원하지 않고, 이러한 문제점을 보완한 다른
표준 입력 함수인 scanf_s 함수를 이용한다.
scanf_s 함수인 경우에는 3번째 argument 값으로 변수의 메모리 사이즈를 넘겨줌으로서 overwriter 발생을 방지 할
수 있으며, 추가적으로 메모리에 overflow 상황이 발생하면 데이터를 메모리에 저장하지 않음으로서 문제를 방지하
게 된다.
같은 이유로 gets 문자열 표준 입력 함수도 보안에 취약하여 최신 버전에서 더 이상 지원하지 않으며, 이를 보완한
gets_s 함수를 사용하게 된다.
6. Short circuit rule은 무엇인가?
논리 연산 과정에서 논리 연산자에 따라 추가적인 평가없이 곧바로 결과를 결정할 수 있는 상황을 "Short circuit" 이라고 한다. 이를 이해하게 된다면 효율적으로 코드를 작성할 수 있는 동시에 동작 시간을 단축시킬 수 있다.
6.1) OR 연산자
→ OR 연산자는 둘 중 하나만 True면 1를 출력하기 때문에 앞의 조건이 True면 뒤의 조건은 볼 필요 없이 바로 1을
출력하게 된다.
6.2) AND 연산자
→ AND 연산자는 둘 중 하나라도 False면 0을 출력하기 때문에 앞의 조건이 False면 뒤의 조건은 볼 것도 없이 바로
0을 출력하게 된다.
하지만, 이를 잘못 이해하거나 잘못 사용하게 되면 논리 에러를 발생시킬 수 있기 때문에 이를 주의하고 사용해야 한다.