일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 29 | 30 |
- c# winform
- C# delegate
- Houdini
- docker
- 깃
- c# 윈폼
- dart 언어
- jupyter
- 도커
- jupyter lab
- c언어
- Unity
- gitlab
- Algorithm
- git
- Flutter
- c#
- 플러터
- HTML
- vim
- 구조체
- Python
- 포인터
- c# 추상 클래스
- C++
- 유니티
- 다트 언어
- github
- Data Structure
- C언어 포인터
- Today
- Total
목록전체 글 (507)
nomad-programmer

과거에는 컴퓨터 시스템의 메모리 용량이 작아 프로그래머들은 메모리를 최대한 적게 사용하도록 프로그램을 개발했다. 허나 최근 메모리 용량이 점차 늘면서 메모리를 더 사용하더라도 프로그램의 실행 속도가 향상되도록 프로그램을 개발하고 있다. 구조체의 경우 다양한 크기의 메모리를 하나의 그룹으로 묶어 사용하다 보니 구조체 요소를 접근할 때 실행 속도가 떨어지는 문제가 발생한다. 그래서 구조체의 요소를 일정한 크기로 정렬하여 실행 속도를 더 빠르게 하는 개념이 C언어 컴파일러에 추가되었다. 컴파일러마다 용어의 차이는 있지만 마이크로소프트에서 제공하는 C컴파일러의 경우에는 "구조체 멤버 정렬" 기능을 제공하며 1, 2, 4, 8바이트로 정렬 기준을 설정할 수 있다. #pragma warning(disable: 49..
visual studio에서 scanf 혹은 printf, getchar 등 함수를 쓰게되면 안전하지 않다는 오류가 발생한다. 이 오류는 쓰고 있는 함수들이 버퍼 오버플로우라는 위험을 가지고 있는 함수라 강력하게 제제하는 오류이다. 그래서 scanf함수는 scanf_s함수로, printf함수는 printf_s함수로 변경하여 사용하라는 메시지이다. 이 메시지를 비활성화하려면 아래와 같은 명령을 파일 최상단에 쓰면 된다. // 4996은 오류 메시지의 번호다. #pragma warning(disable: 4996)
typedef 는 타입을 정의한다는 의미의 "type define"의 줄임 표현이다. 기존의 자료형 중에 자료형 이름의 길이가 긴 경우 프로그래머가 짧고 간결하게 자료형을 재정의하는 문법이다. #define과 비슷해 보이지만 #define은 치환 작업을 수행하는 전처리기이고 typedef는 기존 자료형을 다른 이름으로 새롭게 정의하는 기능이다. 기존 자료형을 단순한 형태의 새 자료형으로 typedef 문법이 가장 흔하게 사용되는 경우는 기존 자료형의 이름이 너무 길어서 새로운 자료형으로 재정의해야 할 때이다. typedef unsigned short int US; // unsigned short int temp; 라고 선언한 것과 같다. US temp; 새롭게 정의했다는 의미를 전달하게 위해 새로 정의한..
https://nomad-programmer.tistory.com/87 [C] 2차원 배열 같은 2차원 포인터의 동적 할당 열의 개수가 행 별로 각기 다르다면 2차원 배열로 생성할 시 메모리 낭비가 불가피하다. 허나, 2차원 포인터로 동적 할당하여 2차원적으로 구조를 생성하면 메모리를 낭비하지 않는 타이트한 메� nomad-programmer.tistory.com 위의 2차원 포인터 동적 할당 포스터중의 예제에서 확장한 것이다. #include #include int main(void) { unsigned int*** arr3d; unsigned int cnt3d; unsigned int cnt2d; unsigned int cnt1d; unsigned int temp; fputs("x축 개수: ", st..
열의 개수가 행 별로 각기 다르다면 2차원 배열로 생성할 시 메모리 낭비가 불가피하다. 허나, 2차원 포인터로 동적 할당하여 2차원적으로 구조를 생성하면 메모리를 낭비하지 않는 타이트한 메모리 구조를 생성할 수 있다. #include #include int main(void) { unsigned int** arr2d; unsigned int cnt2d; unsigned int cnt1d; unsigned int temp; fputs("x축 개수: ", stdout); scanf_s("%d", &temp); arr2d = (int**)malloc(temp * sizeof(int*)); //cnt2d = temp; 아래의 연산과 같음. heap영역에 동적 할당하여 _msize함수 사용 cnt2d = (_ms..
#include #include #include #include void SetData(unsigned short** dst, unsigned short** src, const short size) { for (int i = 0; i < size; i++) { *(*(dst)+i) = *(*(src)+i); } } void Push(unsigned short** ptr, short* curt, const short value) { (*curt)++; unsigned short* new_data = (unsigned short*)malloc(((*curt) + 1) * sizeof(short)); SetData(&new_data, ptr, *curt); *(new_data + (*curt)) = value..
#include #include int main(void) { // depth가 2, 행이 3, 열이 4인 배열을 동적 할당으로 heap 영역에 할당. char (*data)[3][4] = (char***)malloc(sizeof(char) * 2 * 3 * 4); for (int i = 0; i < (2 * 3 * 4); i++) { *(*(*(data + (i / (3 * 4))) + ((i / 4)) % 3) + (i % 4)) = i; } for (int i = 0; i < (2 * 3 * 4); i++) { printf("%-2d ", *(*(*(data + (i / (3 * 4))) + ((i / 4)) % 3) + (i % 4))); if ((i % 4) == 3) { puts(""); } ..
#include int main(void) { char data[3][5] = { {0,}, {0,}, {0,} }; // 2차원 배열의 주소를 저장할 수 있는 포인터 char (*ptr)[5] = data; /* char형 주소값 2개를 저장할 수 있는 배열 */ // char* ptr2[2] = { &data[0][0], &data[1][2] }; // 위의 코드와 같은 초기화 선언이다. char* ptr2[2] = { &(*(*(data+0)+0)), &(*(*(data+1)+2)) }; // data[1][1]에 5저장 (*(ptr+1))[1] = 5; // data[2][0]에 77저장 ptr[2][0] = 77; // data[2][1]에 99저장 *(*(ptr + 2) + 1) = 99; /..
#include int main(void) { int arr[2] = { 0x12345678, 0x12345678 }; printf("%-20s: %p, %p\n", "original", arr[0], arr[1]); // 이렇게 인덱스로만 값을 대입시키면 4바이트 전체가 변경된다. arr[1] = 0x01; printf("%-20s: %p, %p\n", "arr[1]", arr[0], arr[1]); // 1바이트만 변경할 것이라 char 포인터형으로 변경 (char*)arr[1] = 0x01; printf("%-20s: %p, %p\n", "(char*)arr[1]", arr[0], arr[1]); // 1바이트만 변경할 것이라 char 포인터형으로 변경. (char*)arr[1] 과 같은 뜻. *(..
#include #include #include // 최대 길이 설정하여 arr에 문자열 저장 int GetString(char* arr, int limit) { for (int i = 0; i < limit; i++) { arr[i] = getchar(); if (arr[i] == '\n') { arr[i] = '\0'; return 1; } } // 표준 입력 버퍼를 비운다. rewind(stdin); arr[0] = '\0'; return 0; } // atoi 함수의 기능을 새롭게 정의하였다. int Str2Num(char* arr) { int res = 0; int cnt = 0; while (arr[cnt] != '\0') { res = (res * 10) + (arr[cnt] - '0'); ..
대상의 크기가 정해져 있지 않은 void *형 포인터 대상의 크기를 모른다면? 이때 사용하는 것이 바로 void 키워드이다. void 키워드는 '정해져 있지 않다'는 의미를 가지고 있다. void* ptr; 이렇게 선언하면 ptr에 주소 값을 저장할 수는 있지만 해당 주소에서 값을 읽거나 저장할 때 사용하는 크기는 정해져 있지 않다. 즉 사용할 메모리의 시작 주소만 알고 끝 주소를 모를 때 사용하는 포인터 형식이다. void 포인터는 가리킬 대상의 크기를 정한 것이 아니라서 어떤 크기의 메모리가 오든지 상관 없다. 그렇다면 void * 로 선언한 포인터 변수를 주소 값만 저장하는 용도로 사용하는 것은 아니다. 적절한 형 변환을 거쳐 '사용할 크기'를 표기해 주면 일반 포인터처럼 사용할 수 있다. int ..
// 총 4바이트 0x12345678 빅 엔디안 - 리눅스, 유닉스 등은 빅 엔디안 방식이다. 큰 수의 비트부터 읽어 들이고 메모리에 저장할 때도 마찬가지로 큰 비트를 먼저 메모리에 올린다. 즉, 위의 16진수 같은 값이 있다면 0xAAA1 주소에 0x12가 올라가고 그 다음 0xAAA2 주소에 0x34 값이 올라가고 그 다음 0XAAA3 주소에 0x56 값이 올라가고 마지막 0x78은 0xAAA4 주소에 올라간다. 0xAAA4 0x78 0xAAA3 0x56 0xAAA2 0x34 0xAAA1 0x12 위의 표 처럼 메모리에 올라간다. 리틀 엔디안 - 윈도우즈는 리틀 엔디안 방식이다. 작은 수의 비트부터 읽어 들이고 메모리에 저장할 때도 마찬가지로 작은 비트를 먼저 메모리에 올린다. 0xAAA4 0x12 ..