Computer Science
탄탄한 기반 실력을 위한
전공과 이론 지식 모음
Today I Learned!
배웠으면 기록을 해야지
TIL 사진
Flutter 사진
Flutter로 모바일까지
거꾸로캠퍼스 코딩랩 Flutter 앱개발 강사
스파르타코딩클럽 즉문즉답 튜터
카카오테크캠퍼스 3기 학습코치
프로필 사진
박성민
임베디드 세계에
발을 들인 박치기 공룡
임베디드 사진
EMBEDDED SYSTEM
임베디드 SW와 HW, 이론부터 실전까지
ALGORITHM
알고리즘 해결 전략 기록
🎓
중앙대학교 소프트웨어학부
텔레칩스 차량용 임베디드 스쿨 3기
애플 개발자 아카데미 1기
깃허브 사진
GitHub
프로젝트 모아보기
Instagram
인스타그램 사진

TIL

[251017] Day 67 - Cㅂ 또 까먹었네

sm_amoled 2025. 10. 18. 16:59

들어가며

오늘 아침에 크로스핏 출석 예약을 해두고 너무 피곤해서 못나갔다. ㅜㅜㅜ 12시에 눕는것도 좀 늦나보다. 앞으로는 11시 반에 누우려고 노력할 것.

오늘 C언어 테스트를 봤다.

1달 지나긴 했어도 C로 코드 작성하는 것과 개념들을 잘 배워서 기억하고 있다고 생각했는데, 아니였군 아니였어. 강사님께서 다른 기업에서 요청을 받아 돈받고 출제했던 문제들이라서 문제 자체를 공유할 수는 없겠지만, 내가 놓쳤던 부분들에 대해서는 컨셉과 키워드를 잘 적어두려고 한다.

오늘의 키워드

C언어 테스트 오답노트

배열과 Union을 사용할 땐 메모리 번지수 계산을 잘하자

번지수 계산을 잘하자. 단순히 그냥 배열에서 몇 번째? 이런거 판단할때는 왼쪽에서 오른쪽으로 읽는게 자연스럽지만, bit 단위의 계산과 메모리 단위의 계산을 하는 시점에는 숫자는 오른쪽에서 왼쪽으로 읽는다는 것을 유념해야한다.

여러번 Pointer를 타고 넘어가는 상황에서는 타입을 보면 된다

// a 배열에 대한 선언
// b 배열에 대한 선언
const int * const * arr[3] = {a, b, c};

// 위 상황에서 아래 코드가 에러가 발생할까?
arr[0][1][2] = 3;

요런 느낌으로 수식이 있을 때, arr 에서 pointer로 참조 연산을 할 때는 a, b 배열의 타입은 전혀 고려대상이 아니다. 단지 arr 의 타입에 뭐라고 적혀있는지가 중요하다.

 

arr          -> const int* const* [3] (수정 가능한 포인터를 담은 배열)
arr[0]       -> const int* const* (수정 가능한 포인터)
arr[0][1]    -> const int* const (수정 불가능한 포인터)
arr[0][1][2] -> const int (수정 불가능한 값)

// 따라서 arr[0][1][2] 에는 값을 할당할 수 없다.

나는 이거를 arr[0]을 하는 순간 a 배열의 타입을 찾아서 수정 가능 여부를 확인해야 한다고 생각했는데, 그런게 아니였어… 그냥 arr 에서의 타입만 확인하면 되는 것이였다.

 

만약에 아래처럼 코드가 있었다면 에러가 발생하지 않았을 코드임!

int * const * arr[3] = {a, b, c};
arr[0][1][2] = 3;

정수의 승격

정수의 승격이 나는 [ 연산 속에서 가장 큰 타입으로 일치가 된다 + unsigned 가 signed 타입보다 큰 타입이다 ] 의 규칙이라고 생각하고 있었는데, 오늘 문제를 풀었다가 틀리고 다시 한 번 확인해보니 “signed int 보다 작은 타입은 모두 signed int로 승격한 뒤에 연산한다” 라는 내용이 있었다. 심지어 내가 블로그에 적었음 ㅋㅋ

생각하자.

  • 연산 속에서 가장 큰 타입으로 일치가 된다
  • unsigned 가 signed 타입보다 큰 타입이다
  • signed int 보다 작은 타입은 모두 signed int로 승격한 뒤에 연산한다

약간 의아한 점은, 64bit 아키텍처에서는 32bit의 정수 타입인 int32_t 로 굳이 변경할 필요 없이 int64_t 로 승격하는게 연산이 더 빠르지 않을까? 라고 생각이 들었다. 그래서 혹시 64bit에서는 8byte로 승격이 발생하나? 찾아보니 다음의 내용들이 있었다.

  • 32bit → 64bit 으로 넘어갈 때에는 메모리 주소 지정에 대한 니즈는 있었으나 int 타입의 확장 (4byte → 8byte) 에 대한 니즈는 없었음.
  • 전통적으로 int 타입은 32bit로 30년 넘게 사용해왔음. 이걸 함부로 변경하면 Portability 이슈와 호환성 이슈가 발생할 수 있음.
  • 일반적으로 CPU가 64bit 를 채택했다고 하더라도 32bit 정수 연산을 위해 나머지 32bit는 0으로 채워버리는 도구를 사용하기에 64bit 아키텍처에서 32bit 로 연산을 하더라도 느리지 않음.

https://unix.org/version2/whatsnew/lp64_wp.html

관련된 내용이 궁금하다면 여기에서 Portability 와 Technical Choice 등의 내용을 읽어보자!

상수를 적으면 일단 int32_t?

열심히 적다보니 내용이 좀 괜찮은 것 같아서 따로 아티클로 빼냈다. 대충 정수 Literal 로 적으면 C 컴파일러가 어떤 타입으로 이걸 판단하는지에 대한 내용을 담고있다. 내가 알고 있던 부분도 있는데 몰랐던 유레카 부분도 있어서 참고하면 좋을 것 같아 기록으로 남겼다.

 

상수를 적으면 일단 int32_t?ㅤ 에서 확인하자!

 

[C언어] 상수를 적으면 일단 int32_t?

자꾸 헷갈렸다. 이것도 사실 정수의 승격이랑 비슷한건데…ㅤ사실 아래 3가지는 모두 동일한 의미를 가진다. 뒤에 숫자를 적어서 값을 대입하는건 형식과 전혀 관계없는 과정임. 결국 일단 작성

etst.tistory.com

 

,는 병렬연산자

이런 형식의 문제가 나왔다.

if ( a > 0, b > 0 ) { ... }

언듯 보기에는 a와 b 모두 조건 검사를 수행할 것 같지만, 사실 여기에서 a > 0 은 비교를 수행하긴 하는데 결과를 조건문의 조건으로 이용하지 않고 콤마 가장 마지막에 있는 b > 0 만 조건으로 이용한다. (아마 여기에서 a > 0 은 컴파일러가 최적화를 하면서 지워버릴 수도 있을 것 같다) 콤마는 병렬연산자. 이 문제 틀리지는 않았던 것 같은데 고려하지 않았던 부분이라 남겨둔다. 기억할 것!!

 

프로세서 아키텍처

회사의 제품 종류에 따라서 필요로 하는 스펙이 달라진다.

  • 서비스 (SI)
  • 세트 (삼성DX, LG전자)
    • 전체 제품
  • 모듈 (삼성DS, 디스플레이, 장비)
    • 펌웨어 개발 (OS 없이 프로그램 올리기)
    • C/C++
    • HW의 발전으로 OS 올리는 경우가 점점 더 많아질 것 같음.

OS가 없는 환경에서는 펌웨어가 직접 HW의 정보를 조작한다.

OS가 있는 환경에서는 System Call을 통해 OS에게 정보 및 조작을 요청한다.

신뢰성이 중요한 영역일수록 빠른 개발보다는 엄밀한 개발이 중요해진다.

MISRA-C, Testcode, 안전한 코드 같은 것들을 내가 기술력으로 보여줄 필요가 있을까?

컴퓨터의 BUS 구조

  • address bus
  • data bus
  • control bus

프로세서

  • 프로세서
    • CPU : ALU + Register + Control Unit 을 포함하는 유닛
    • Micro Processor : 하나의 칩 위에 올라가있으면 마이크로 프로세서
    • = MPU
    • Co-processor (FPU, GPU 등 … 프로세서 내부에 있는 친구들)
  • SoC
    • Micro Controller : peripheral 이 포함됨
    • = MCU
    • MICOM : 저성능 저사양 저가의 MCU

  • AP (Application Processor) : Windows, Linux 같은 범용 OS의 탑재용 - MMU가 반드시 필요함

320x100