[2024.03.11.월] 인천인력개발원 하만 세미콘 아카데미
임베디드 시스템을 위한 SW 구조설계
변수와 연산자
- 대입 연산자: =, +, -, *, /, %
- 축약형태
- a = a + b; => a += b;
- a = a - b; => a -= b;
- a = a * b; => a *= b;
- a = a / b; => a /= b;
- a = a % b; => a %= b;
- 축약형태
- 증감 연산자
- ++a : 선 증가, 후 연산
- a++ : 선 연산, 후 증가
- --b : 선 감소, 후 연산
- b-- : 선 연산, 후 감소
- [example]
int a = 10; printf("%d", ++a); //=> 11출력 int b = 10; printf("%d", b--); //=> 10출력 후 b 값 9로 변경
- 관계 연산자(비교 연산자)
- 두 피연산자의 관계 비교
- true(1), false(0) 반환
- <. >, ==(같다), !=(같지 않다), <=, >=
- 관계 연산자 왼쪽 피연산자가 기준이 됨
- [example]
1 < 3 => 결과값 1,
1 == 3 => 결과값 0
- 논리 연산자
- and, or, not 표현
- true(1), false(0) 반환
- &&: 피연산자가 모두 true면 true 반환 (AND) [ex) a&&b]
- ||: 피연산자 하나라도 true면 true 반환 (OR) [ex) a||b]
- !: true면 false를, false면 true를 반환 (NOT) [ex) !a] - C언어에서는 0이 아니면 true로 간주
- 비트 단위 연산자: ~(NOT), &(AND), |(OR), ^(XOR), <<, >>
- [example]
a: 1010(2)
b: 0101(2)인 데이터에 대하여
a&b => 각각의 비트(같은 자릿수)가 연산 대상 => 결과: 0000(2)
a|b => 결과: 1111(2) = 15(10)
~a => 결과: 0101(2) = b - <<, >> : shift연산자(비트를 이동시키는 연산자)
- 새로 생긴 자리는 0, 넘어간 비트는 삭제 - XOR examples
- 1^1 = 0
- 0^1 = 1
- 1^0 = 1
- 0^0 = 0
- [example]
- 콤마(,) 연산자
- 둘 이상의 변수 동시 선언 시
- 둘 이상의 문장을 한 줄에 선언 시
- 함수의 매개변수 전달 시
- 연산자의 우선 순위(괄호를 이용하여 명시적으로 구분하기)
① *, /
② +, -
데이터 표현 방식
- 진법에 대한 이해
- 2진수 표현 범위: 0~1
- 8진수 표현 범위: 0~7
- 10진수 표현 범위: 0~9
- 16진수 표현 범위: 0~9+A~F (FF(16)=255(10))
- 데이트 표현 단위 비트(bit), 바이트(byte)
- 비트 : 데이터 표현 최소 단위. 0 or 1 저장
- 바이트 = 8비트
- 정수 표현 방식
- MSB(Most Significant Bit): 가장 왼쪽 비트. 부호 표현
- LSB(Least Significant Bit): 가장 오른쪽 비트
- MSB 제외 나머지 비트: 데이터의 크기 표현
- 00000001 => 맨 앞 0은 부호(+/-) 표현
- shift(<<, >>) 연산자
- a<<b: a의 비트들을 b칸씩 오른쪽으로 이동한 값 반환
- 8>>2: 8의 비트를 왼쪽으로 2칸씩 이동한 값 반환
상수와 기본 자료형
- 자료형: 선언할 변수의 특징을 나타내는 키워드
- 기본 자료형: 기본 제공 자료형
- 정수형 종류: 표현 가능 데이터 범위
- char(1byte): -128 ~ +127
- short(2byte): -32768~ +32767
- int(4byte): -2147483648 ~ +217483647
- long(4byte): -2147483648 ~ +217483647 - 실수형 종류: 표현 가능 데이터 범위
- float(4byte): 3.4*10^(-37) ~ 3.4*10^(+38)
- double(8byte): 1.7*10^(-307) ~ 1.7*10^(+308)
- log double(8byte~)
- 정수형 종류: 표현 가능 데이터 범위
- 자료형 선택 기준
- 정수는 int
- 실수형 데이터(정밀도 기준)
- 정밀도: 오차 없이 표현 가능한 정도
- float: 소수 이하 6자리
- double: 소수 이하 15자리
- long double: double의 정밀도 이상
- ASCII 코드
- 미국 표준협회(ANSI)에서 정의
- 컴퓨터에서 문자를 표현하기 위한 표준
- 문자-숫자 연결관계 정의
ASCII 코드 - ASCII 코드 범위 : 0~127 char형 변수로 처리 가능
- 문자는 따옴표(' ')로 표현
- 리터럴(literal) 상수: 이름이 없는 상수(30, 40과 같은 값)
- 상수가 메모리 공간에 저장되기 위해 자료형 결정(컴파일러가 자동으로 변수 자료형도 결정)
- char c = 'A'; => 문자상수(char)
- int i = 5; => 정수상수(int)
- double d = 3.15; => 실수상수(double)
- 상수가 메모리 공간에 저장되기 위해 자료형 결정(컴파일러가 자동으로 변수 자료형도 결정)
- 접미사에 따른 상수 표현( 접미사 | 자료형 | 예시 )_error 발생 전까지는 굳이 사용 x
- u or U | unsigned int | 304U
- l or L | long | 304L
- ul or UL | unsinged long | 304UL
- f or F | float | 3.15F
- l or L | long double | 3.15L
- 심볼릭 상수
- const키워드를 통해 변수를 상수화
- [example]
이 경우는 선언과 동시에 초기화 필수#include <stdio.h> int main(void) { const int MAX=100; const double PI=3.1415; }
- 자료형 변환
- 자동 형 변환: 다른 자료형의 변수(int a)를 다른 변수(float b)에 대입할 때 발생
[example1: 대입 연산 시]
#include <stdio.h> int main(void) { int n=5.25; //소수부 손실 double d=3; //값의 표현이 넓어짐 char c=129; //상위 비트 손실 }
[example2: 정수의 승격에 의해]
#include <stdio.h> int main(void) { char c1=10, c2=20; char c3=c1+c2; //... }
- 강제 형 변환: 프로그래머가 명시적으로 요청하는 형 변환
- cast연산자 사용
#include <stdio.h> int main(void) { float f=(float)3.14; //3.14를 float형으로 형 변환 double e1 = 3 + 3.14; //정수 3이 double형으로 자동 형 변환 double e2 = 3 + (int)3.14; //3.14가 int형으로 강제 형 변환 }
- 자동 형 변환: 다른 자료형의 변수(int a)를 다른 변수(float b)에 대입할 때 발생
반복문
- 세가지 반복문
- while 반복문
- do~while 반복문
- for 반복문
- while 반복문
while( 반복조건 ) { 반복 내용 }
- "반복 조건"이 만족되는 동안 "반복 내용" 반복 실행
[example]
: i<10이 만족되는 동안 printf()와 i++을 반복 실행- 무한 루프에 빠지지 않도록 탈출조건 설정!!while( i<10 ) { printf("Hello World! \n"); i++; }
- while문에서 중괄호: 반복 영역이 둘 이상의 문장일 경우 필수
- 무한루프: 반복 조건으로 true(0이 아닌 정수)일 경우 발생, 탈출조건 x
while(1){ printf("Hellow World!\n"); i++; }
- do~while과 while의 차이: do~while은 한 번 실행한 뒤 조건 검사/ while은 실행 전 조건 검사
- for 반복문: 초기문, 조건문, 증감문을 모두 포함
for(초기문; 조건문; 증감문) { 반복내용 }
- for문 vs while문
[for문 예시]
int i; for(i=0; i<10; i++){ printf("Hello World!\n"); }
[while문 예시]
int i; i=0; while(i<10){ printf("Hello World!\n"); i++; }
조건문
- if 조건문
if (실행 조건) { 실행 내용 }
- if~else 조건문
if (실행 조건) { 조건 만족 시 실행 } else { 조건 불만족 시 실행 }
- if, else if, else
=> 실행 시간이 오래걸려 좋은 방법 Xif(조건 A) { 조건 A 만족 시 실행 } else if(조건 B) { 조건 A 불만족, B 만족 시 실행 } else if(조건 C) { 조건 A 불만족, B 불만족, C 만족 시 실행 } else { 조건 A, B, C 모두 불만족 시 실행 }
- if~else 조건문
- switch문(분기의 수가 많아지면 가급적 switch 사용)
switch (n) { case 1: n이 1인 경우 실행 영역 break; case 2: n이 2인 경우 실행 영역 break; case 3: n이 3인 경우 실행 영역 break; default: 해당 case 없을 시 실행 }
- switch문에서는 조건식에 비교 연산 불가능
- 삼항 연산자(조건 연산자)
- if~else 문을 간결히 표현하는 데 사용 가능
-
조건 ? A : B; //조건을 만족하면 A 실행, 불만족하면 B 실행
- break: 반복문을 빠져나올 때 사용(반복문의 종료 지점 다음 줄의 코드 실행)
- continue: 다음 번 반복으로 넘어갈 때 사용(반복문의 조건식으로 돌아감)
- goto label
- 이동할 위치 표시를 위한 레이블(label:) 선언
- go to lable; => 레이블 위치로 실행 위치 이동
- 프로그램의 흐름이 복잡해지므로 사용 지양
조건문 실습
실습 주제: if문을 이용하여 숫자키를 누르면 해당 영어단어를 출력하는 프로그램 작성
scanf: 한 값을 입력할 때 마다 엔터키를 눌러야 입력 완료
=> 키 하나만 입력받는 함수: getch(키 값을 출력하지 않고 반환)
- if조건문을 이용하여 1 입력 시 One을 출력하는 프로그램
#include <stdio.h> #include <conio.h> int main(void) { printf("숫자키를 입력하면 해당 영단어를 표시합니다.\n"); printf(">"); char c = _getch(); if(c=='1'){ printf("One\n"); } }
'1' 입력 시 'One' 출력하는 코드 작성 실행 결과 - Select~Case를 이용하여 숫자 입력 시 영단어를 출력하는 프로그램
#include <stdio.h> #include <conio.h> int main(void) { while (1) { printf("숫자키를 입력하면 해당 영단어를 표시합니다.(x는 종료)\n"); printf(">"); char c = _getch(); printf("%c\n", c); if (c == 'x') break; switch (c) { case '1': printf("One\n"); break; case '2': printf("Two\n"); break; case '3': printf("Three\n"); break; case '4': printf("Four\n"); break; case '5': printf("Five\n"); break; case '6': printf("Six\n"); break; case '7': printf("Seven\n"); break; case '8': printf("Eight\n"); break; case '9': printf("Nine\n"); break; case '0': printf("Zero\n"); break; } printf("\n"); } }
각 숫자 입력값에 맞는 단어 표시 및 x 입력 시 종료 - Select~Case를 이용하여 숫자 입력 시 영단어를 출력하는 프로그램+이외 글자 입력 시 에러 표시
종료 조건문에 x | 0x20 == 'x'를 입력하면 입력 값을 소문자로 변환하여 종료 진행#include <stdio.h> #include <conio.h> int main(void) { printf("숫자키를 입력하면 해당 영단어를 표시합니다.(x는 종료)\n"); while (1) { printf(">"); char c = getch(); printf("%c\n", c); if (c == 'x' || c == 'X') break; switch (c) { case '1': printf("One\n"); break; case '2': printf("Two\n"); break; case '3': printf("Three\n"); break; case '4': printf("Four\n"); break; case '5': printf("Five\n"); break; case '6': printf("Six\n"); break; case '7': printf("Seven\n"); break; case '8': printf("Eight\n"); break; case '9': printf("Nine\n"); break; case '0': printf("Zero\n"); break; default: printf("숫자가 아닙니다.\n"); break; } printf("\n"); } }
숫자와 x 이외의 문자 입력 시 오류 표시
#include <stdio.h> #include <conio.h> int main(void) { printf("숫자키를 입력하면 해당 영단어를 표시합니다.(x는 종료)\n"); while (1) { printf(">"); char c = getch(); printf("%c\n", c); if (c == 'x' || c == 'X') break;//c | 0x20 == 'x'로 조건 넣어도 작동. c | 0x20을 통해 입력 값을 소문자로 변환 switch (c) { case '1': printf("One\n"); break; case '2': printf("Two\n"); break; case '3': printf("Three\n"); break; case '4': printf("Four\n"); break; case '5': printf("Five\n"); break; case '6': printf("Six\n"); break; case '7': printf("Seven\n"); break; case '8': printf("Eight\n"); break; case '9': printf("Nine\n"); break; case '0': printf("Zero\n"); break; default: printf("숫자가 아닙니다.\n"); break; } printf("\n"); } }
[case 코드 정리]
*단축키 참고
- 전체적으로 들여쓰기를 정렬하려면 Ctrl+K 입력 후 Ctrl+F
- 일부 전체를 주석처리 : 드래그 후 Ctrl+K -> Ctrl+C
- 주석처리 해제 : 드래그 후 Ctrl+K -> Ctrl+U
1차원 배열
- 둘 이상의 변수 동시 선언 효과
- 많은 데이터의 일괄적 처리에 유용
- 배열 선언 필요 요소 3가지
- 배열 길이: 배열 구성 변수의 개수(상수 사용) = 방의 개수
- 배열 요소 자료형: 배열 구성 변수의 자료형
- 배열 이름: 배열 접근 시 사용할 이름
- [example]
int array [10]; => int: 배열 요소 자료형/ array: 배열 이름/ 10: 배열 길이
- n차원 배열
- 1차원 배열: 직렬로 같은 자료형의 배열을 나열
- 2차원 배열: 1차원 배열이 층을 이루며 올라가는 형태
- 3차원 배열: 육면체 모양의 형태
- 1차원 배열의 접근
- 인덱스(index): 배열 요소의 위치 표현
- 인덱스는 0부터 시작( array[0], araay[1], array[2], ..., array[8], array[9] ) -> "Zerobase"
- 배열 선언&접근 예시
- array[s] = 10; => s+1번째 요소에 10을 대입int main(void){ int array[10]; //배열 선언 array[0]=10; //첫 번째 요소 접근 array[1]=20; //두 번째 요소 접근 array[2]=30; //세 번째 요소 접근 ... return 0; }
- 배열 선언과 동시에 초기화
int main(void) { int arr1[5] = {1, 2, 3, 4, 5}; int arr2[] = {1, 3, 5, 7, 9}; int arr3[5] = {1, 2}; }
- int arr1[5] = {1, 2, 3, 4, 5};
=> int arr1[5]: 길이가 5인(변수가 5개인) 배열 생성/ {1, 2, 3, 4, 5}: 초기화 리스트
=> 배열을 생성하여 초기화 리스트로 각 요소 초기화
=> 배열: [ 1 2 3 4 5 ] - int arr2[] = {1, 3, 5, 7, 9};
=> int arr2[]: 배열 길이가 정해지지 않았으나, 초기화 리스트를 통해 변수가 5개임을 명시 -> 길이가 5인 배열 생성
=> 배열: [ 1 3 5 7 9 ] - int arr3[5] = {1, 2};
=> 배열 길이가 5개인 배열을 만들고, 앞쪽 배열부터 초기화
=> 배열: [ 1 2 0 0 0 ]
- int arr1[5] = {1, 2, 3, 4, 5};
- 문자열(=문자의 배열) 상수: 문자열이면서 상수의 특징
- 문자열 변수: 문자열이면서 변수의 특징
char str1[5] = "Good"; -> 총 5개의 방 포함 배열
char str2[] = "morning"; -> 총 8개의 방 포함 배열 - 문자열 특징
- 널(null)문자('\0', 아스키코드 0)가 문자열 끝에 위치
- char str[6] = "Hello"; 코드에서, Hello는 5글자이지만 끝에 null을 고려하여 배열의 크기를 6으로 설정
=> 배열을 표시하면 [ H e l l o ( ) ] ( )은 null - Null의 역할: 문자열의 끝 표시/ printf 함수에서 출력 범위 결정
- 문자열 vs. char형 배열
- char arr[] = "abc";
- char arr2[] = { 'a', 'b', 'c' }; => printf 사용 시 c 이후 쓰레기값이 표시될 수 있음
- char arr3[] = { 'a', 'b', 'c', '\0' }; => null을 이용하여 경계 구분
배열을 이용하여 위 실습 코드 수정
- 각각의 배열 요소는 문자열을 나타냄
- 입력 숫자 키 값에서 30H(30Hexa, 16진수 30)를 빼면 ASCII코드에 따른 숫자값이 됨
다음의 코드로 변환 가능
int m = c - 0x30; //ASCII -> num값
- ASCII코드 확인-> 16진수 | 10진수
30 | 0
31 | 1
32 | 2
...
39 | 9 - 코드 변경 및 적용
#include <stdio.h> #include <conio.h> int main(void) { char* str[] = { "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine" }; // 문자열 포인터(*) 배열 선언 printf("숫자키를 입력하면 해당 영단어를 표시합니다.(x는 종료)\n"); while (1) { printf(">"); char c = getch(); printf("%c\n", c); if (c == 'x' || c == 'X') break;//c | 0x20 == 'x'로 조건 넣어도 작동. c | 0x20을 통해 입력 값을 소문자로 변환 int m = c - 0x30; //ASCII -> num값 printf("%c: %s\n", c, str[m]); //입력 값c: str의 m번째 값. printf("\n"); } }
정상 작동 확인
'하만(Harman) 세미콘 반도체 설계 과정 > 임베디드 시스템을 위한 SW 구조설계' 카테고리의 다른 글
하만(Harman) 세미콘 아카데미 6일차 - SW 구조설계(문자와 문자열 처리 / 사용자 정의 함수 구현 ) (56) | 2024.03.14 |
---|---|
하만(Harman) 세미콘 아카데미 5일차 - SW 구조설계(포인터 / 함수 포인터 / 자료형 / 구조체 / 공용체) (64) | 2024.03.13 |
하만(Harman) 세미콘 아카데미 4일차 - SW 구조설계(함수 / 다차원 열 / 포인터) (65) | 2024.03.12 |
하만(Harman) 세미콘 아카데미 2일차 - SW 구조설계(printf / scanf ) (71) | 2024.03.09 |