라벨이 C인 게시물 표시

[C++] 비트 단위로 제어하기

비트 필드는 구조체와 흡사하나 구조체는 byte 단위로 멤버를 사용할 수 있지만 비트 필드는 bit 단위로 멤버를 사용할 수 있다. 그래서 많은 상태를 저장하거나 bit별로 제어해야 하는 경우에 비트 필드를 사용한다. 비트 필드의 멤버는 unsigned형(unsigned int형)과 int형의 멤버를 가질 수 있고 비트 필드 변수의 크기는 int형 크기와 같은 4byte(32bit)이다. signed와 unsigned는 char, short, int, long 등의 자료형 앞에 사용되어 부호가 있는 정수와 부호가 없는 정수를 나타내는 자료형으로 사용되며 signed는 보통 생략하여 사용한다. 비트 필드처럼 unsigned가 단독으로 사용되면 unsigned int형을 간략하게 표현한 형태이다. 다음은 비트 필드를 사용하여 1bit씩 제어하는 예제이다. #include <stdio.h> #include <string.h> struct _bitfield { unsigned b0:1; unsigned b1:1; unsigned b2:1; unsigned b3:1; unsigned b4:1; unsigned b5:1; unsigned b6:1; unsigned b7:1; }; void main() { struct _bitfield bit; memset(&bit, 0, sizeof(struct _bitfield)); bit.b0 = 1; bit.b7 = 1; printf("%d\n", sizeof(struct _bitfield)); printf("%08x %d\n", bit, bit); } memset() 함수를 사용하여 bit 변수 4byte를 0으로 초기화하고 bit.b0와 bit.b7을 1로 만들어 결과는 0x81이 된다. bit 변수는 32bit 중 8bit만을 ...

[C] Command Prompt(명령 프롬프트) 창 띄우지 않고 명령어 실행

#include <iostream> #include <Windows.h> namespace EXEC_COMMAND { namespace RETURN { namespace FAILURE { const int CREATE_PIPE = 1; const int CREATE_PROCESS = 2; } } } int ExecCommand(std::string command, std::string& output); int main() { std::string output; ExecCommand("ping -n 1 142.251.42.164", output); std::cout

Integrity Level SID 값

const char * const INTEGRITY_LEVEL_SID_UNTRUSTED = "S-1-16-0"; const char * const INTEGRITY_LEVEL_SID_BELOW_LOW = "S-1-16-2048"; const char * const INTEGRITY_LEVEL_SID_LOW = "S-1-16-4096"; const char * const INTEGRITY_LEVEL_SID_MEDIUM_LOW = "S-1-16-6144"; const char * const INTEGRITY_LEVEL_SID_MEDIUM = "S-1-16-8192"; const char * const INTEGRITY_LEVEL_SID_HIGH = "S-1-16-12288"; const char * const INTEGRITY_LEVEL_SID_SYSTEM = "S-1-16-16384";

[C] scanf 매개변수(인자)의 형식

scanf() 함수의 입력 형식 기호 바로가기!!! 1. scanf("%3s", str); scanf("%3s", str); 이렇게 할 경우 입력 버퍼로부터 3개의 문자열만을 읽어들이고 나머지는 입력 버퍼에 남아있게 된다. scanf("%3s", str); scanf("%c", &ch); 이렇게 코딩하고 입력시에 "abcdef" 를 입력해주고 출력을 해보면 %3s에서 3을 빼고 %s로 적었을 경우에는 str에 "abcdef"가 입력이 되고 입력 버퍼에 남아있는 엔터값이 ch로 입력이 되어 버리지만 위의 경우에는 str에는 "abc" 3자리만 str에 입력이 되고 ch에는 입력 버퍼에 남아있던 문자열중 첫번째 'd'가 입력이 된다. 2. scanf("%d", &num); scanf("%d", &num); 이렇게 코딩하고 입력을 "123ab45" 이렇게 하면 사용자가 입력한 문자열 맨 처음부터해서 문자가 나오기전까지 정수 부분만 입력이 된다. 따라서 위의 경우 num에는 숫자 123으로 초기화가 된다. 3. scanf(" %c", &ch); scanf(" %c", &ch); 이렇게 %c 앞에 공백을 두면 화이트 스페이스(tab, space bar, enter)가 무시된다. fflush(stdin); 으로 입력 버퍼를 비우는 방법의 경우 윈도우 기반에서는 정상 동작하지만 Unix/Linux, gcc 기반에서는 fflush가 정상적으로 동작하지 않을수도 있다. 4. scanf("%[12345]", str); char str[80] = {0}; scanf("%[12345]", str); // 사용자...

[C] 프로그래밍 방법의 3가지

출처 - 한눈에 보이는 C프로그래밍(무작정 따라하기) 순차적 프로그래밍 컴퓨터가 처리해야 할 순서에 따라 기술하는 방식. 한 번에 하나의 작업만을 할 수밖에 없다는 단점이 있지만 프로그래밍의 구조가 간단하고 작성하기도 쉽기 때문에 지금도 종종 사용되고 있다. 구조적 프로그래밍 기본적인 개념은 중복되어 사용할 수 있는 기능을 하나로 묶는다는 것이다. 다시 말해, 서로 다른 프로그램이라고 할지라도 같은 기능을 사용해야 할 경우라면 굳이 프로그램마다 이 기능을 위해 똑같은 소스 코드를 생성할 필요 없이, 공통 부분의 소스코드를 만들어 놓고 필요한 프로그램에서 이 코드를 사용하면 된다는 것 이렇게 공통적으로 사용할 수 있는 기능을 묶어놓은 것을 모듈 이라고 한다. C언어에서는 함수라고 부른다. 비슷한 기능을 하는 함수들을 묶어놓은 것을 라이브러리라고 한다. 단점으로는 기능별로 분리하여 함수를 만들도록 되어 있기 때문에 필요한 데이터라도 기능에 따라 분리된다는 점과 구조적 프로그래밍으로 작성한 프로그램들은 재사용이 생각보다 어렵다는 점이 있다. 객체 지향 프로그래밍 공통적으로 사용할 수 있는 기능을 따로 추려서 만든 것을 함수 라고 하고 객체 지향 프로그래밍 방법에서는 기능을 따로 추릴 때 그 기능과 관련된 데이터를 함께 묶어서 프로그램을 만드는 개념이 있는데 이것을 클래스라고 한다. 기능과 데이터를 하나로 묶을 수 있기 때문에 구조적 프로그래밍 방법에 비해 프로그래밍 과정이 훨씬 간단해졌다.

[C] 컴파일러와 인터프리터의 차이점

출처 - 한눈에 보이는 C프로그래밍(무작정 따라하기) 인터프리터(Interpreter)도 컴파일러와 비슷한 역할을 한다. 텍스트로 되어 있는 소스 파일을 CPU가 이해할 수 있는 이진 코드로 변환해준다. 그러나 컴파일러가 소스 파일을 번역하여 이진 파일인 오브젝트 파일을 생성하는 것이 비해, 인터프리터는 소스 파일을 한 줄씩 읽어서 이진 코드로 바꾸어 CPU가 바로 실행할 수 있도록 해준다. 이런 특징은 간단한 프로그램의 경우에는 소스 파일을 실행하는 데 컴파일과 링크 등의 과정이 필요없으므로 편리할 수는 있지만, 실행 파일이 생성되지 않으므로 소스 파일을 실행하기 위해서는 항상 인터프리터가 필요하다. 또한, 소스 파일의 첫 번째 줄부터 한줄씩 실행되므로 프로그램의 실행 속도가 컴파일러에 의해 생성된 실행 파일보다 현저하게 느리다.

[C] 컴파일과 빌드의 차이점

출처 - 한눈에 보이는 C프로그래밍(무작정 따라하기) 컴파일(Compile) 이란, 텍스트 형태로 되어 있는 소스 파일을 기계어 파일(바이너리 파일, 이진 파일)로 만드는 과정을 의미한다. 단순히 텍스트 파일로 되어 있는 것을 해당 프로그래밍 언어의 문법에 맞는지 검사하여 특별한 오류가 없다면 기계어 파일로 변경해 준다. 그러나 컴파일 된 파일은 실행 파일이 아니다. 다시 말하면 우리가 윈도우 환경에서 실행할 수 있는 .exe 파일의 형태가 아니라는 의미다. 비주얼 C++에서는 .c로 되어 있는 소스 코드를 컴파일하면 .obj 파일로 변환한다. 마찬가지로 리눅스나 유닉스에서도 .c로 되어 있는 소스 코드를 컴파일하면 .o 파일로 변환한다. 이와 같은 obj 파일이나 .o 파일을 일반적으로 오브젝트(Object) 파일이라고 부른다. 빌드(Build) 는 기본적으로 실행 파일을 만드는 것을 의미한다. 사실상 하나의 소스 파일이 하나의 실행 파일로 생성되기 위해서는 컴파일(Compile) 과정과 링크(Link) 과정을 거쳐야 한다. 링크(Link)라는 것은 말 그대로 실행 파일로 만드는 데 필요한 기능들을 컴파일 된 파일에 연결시킨다는 의미이다. 따라서 .c 파일을 컴파일한 후에 생성된 오브젝트 파일들을 이용하여 링크 작업을 해야 .exe 파일이 생성된다. 비주얼 C++에서는 빌드를 통해서 링크(Link)과정을 실행한다. 만약 .c 파일이 컴파일되어 있지 않은 상태에서 빌드를 실행하면 컴파일과 링크를 모두 실행하며, 이미 .obj로 컴파일 된 파일이 존재하면 빌드를 실행했을 때 컴파일 작업을 생략하고, 링크 작업을 한 후에 실행 파일을 생성하게 되는 것이다.

[C] 오류와 경고의 차이점

출처 - 한눈에 보이는 C프로그래밍(무작정 따라하기) 오류(Error) 는 단 하나라도 발생하면, 해당 소스 파일이 컴파일되지 않습니다. 결국 오류를 모두 수정하지 않고서는 컴파일을 완료할 수 없다는 의미가 된다. 경고(Warning) 는 프로그래머에게 나중에 문제가 발생할지도 모른다는 것을 알려주는 것으로, 컴파일 과정과 실행 파일 생성 과정에는 별 영향을 미치지 않고 무사히 진행된다. 흔히 1~2년 정도 경력을 가진 프로그래머들은 이러한 경고 메시지를 무시하는 경향이 있는데, 이것은 결코 좋은 프로그래밍 습관이 아니다. 오류가 됐던, 경고가 됐던 메시지로 출력된 내용을 보고 오류나 경고가 나타나지 않도록 소스 코드를 올바르게 수정하는 습관을 가져야 한다. 나중에는 무시했던 경고들이 쌓이고 쌓여서 치명적은 오류를 만들어낼 수도 있기 때문이다.

[C] 연산자 우선순위 문제

질문 제목 ||연산과 &&연산 질문 요약 #include<stdio.h> int main() { int x,y,z,k; x = 1; y = 2; z = 3; k = ++x || ++y && ++z; printf("%d %d %d %d\n",k,x,y,z); return 0; } // 결과 값 : 1 2 2 3 질문 내용 결과값이 왜 이렇게 나오는 거죠?? 설명좀 부탁드립니다. 설명 연산자 우선순위 문제인데... 일단 C언어의 연산자 우선순위는 다음과 같다. C언어 연산자 우선순위 바로가기!!! 그리고 이 문제를 알기 위해서는 하나를 더 알아야 하는데... 컴파일러마다 다를수도 있지만 Visual Studio에서는 앞 조건만 봐서 무조건 결과가 참이 나오면 뒷 부분은 연산이 되지 않는다... 무슨 얘기인가 하면 x = 1, y = 1, z = 1 이 있다고 하고 if ( ++x || ++y || ++z ) 이렇게 if문이 있으면 맨 앞 ++x를 보면 참이되고 || 연산자에 의해서 뒷 부분에 어떠한 값이 나와도 참이된다 그럼 ++y, ++z는 아예 분석조차 되지 않는다. 따라서 저 if문 다음에 x, y, z를 출력해 보면 x는 1이 증가해서 2가 되어 있지만 y, z는 그대로 1인것을 확인할 수 있다. 위에서 설명한 것을 먼저 파악하고 계속해서 문제를 보면 k = ++x || ++y && ++z; 이 라인에서 ++x 만 증가하고 y와 z는 그대로라고 생각할 수 있다. (k의 값은 연산 결과가 참이기 때문에 1이 들어갈 것이라고 짐작할 수 있다.) 그럼 결과가 1, 2, 2, 3이 맞다. 그러나! 여기서 연산자 우선순위를 다시 한번 확인해보자... 분명히 || 보다 &&가 더 빠르다!!! 그럼 y와 z를 먼저 비교하고 다음으로 x와 비교하게 되기 때문에 당연...

[C] 연산자 우선순위

https://msdn.microsoft.com/ko-kr/library/2bxt6kc4.aspx 동일 순위끼리 봤을 때, 왼쪽에 있는 것이 더 순위가 높다. (expr++가 *보다 우선순위가 높다) int *a; int b = 3; a = &b; *a++;        // *(a++)과 같은 결과다!!!

[C] C언어의 장점

출처 - 한눈에 보이는 C프로그래밍(무작정 따라하기) 1. 어셈블리어나 이전 코드(기계어 코드)와 같이 하드웨어를 프로그래밍 할 수 있는 기능을 갖추고 있으면서도 인간이 이해하기 쉬운 고급 언어에 속한다는 점. 2. 이전의 언어들에 비해 매우 다양해진 연산자들. 물론 C언어 이후부터 등장한 언어들은 C언어를 모델로 하여 C언어만큼 다양한 연산자를 갖추고 있다. 3. 쉽게 응용하여 새로운 기능을 만들어 낼 수 있는 유연성. 물론 지금에 와서는 C언오보다는 C++이나 자바와 같은 객체 지향 프로그래밍 언어들의 가장 큰 장점이 되고 있는 부분이다. 4. 운영체제 프로그래밍. 하드웨어 프로그래밍을 비롯한 거의 모든 프로그램 제작이 가능한 범용성을 갖고 있다. 5. C언어로 작성한 프로그램은 윈도우나 유닉스에서 쉽게 이식하여 사용할 수 있다.

[C] C프로그래밍이 실행되기까지

출처 - 한눈에 보이는 C프로그래밍(무작정 따라하기) 원시 소스 파일을 만든다. 메모장과 같은 텍스트 편집기를 입력한 후 .c라는 확장자로 저장 이 파일은 프로그래머에 의해서 만들어진 원본이라는 점과 실행되지 않는 파일이라는 점에서 원시 파일, 원시 소스라고 부른다. 비주얼 C++에 포함된 자체 텍스트 편집기를 사용해도 됨. 컴파일러를 이용해 이진 코드로 바꾼다. 원시 파일을 컴퓨터가 이해할 수 있도록 C프로그램의 소스 코드를 이진 코드로 바꿔주는 프로그램을 필요로 한다. 이런 프로그램을 컴파일러(번역기)라고 한다. 소스 코드를 작성한 후에 컴파일러를 사용하여 소스 코드를 기계어로 번역한다. 이 과정을 컴파일(compile)이라고 하며, 컴파일되어 번역된 파일을 오브젝트(목적 코드)파일 이라고 한다. 링크 명령을 이용해 실행 파일로 만든다. 두 개 이상의 소스 파일을 사용하여 하나의 실행 파일로 만들거나, 컴파일러에서 기본적으로 제공하는 여러 가지 라이브러리 등을 사용자가 만든 프로그램에 연결해 주는 것을 말한다. 그러므로 링크 과정을 거쳐야 비로소 실행 파일이 생성되고, 그 실행 파일을 실행시키면 출력 결과가 나타나게 되는 것이다.

[C] C언어의 지시어(헤더파일, 전처리, 매크로)

미리 정의된 매크로 https://docs.microsoft.com/ko-kr/cpp/preprocessor/predefined-macros?view=msvc-160 // 미리 정의된 include 폴더에서 파일을 찾는다. #include <파일이름> // 현재의 소스 코드가 저장되어 있는 폴더에서 먼저 찾고, 파일이 없다면 미리 정의된 include 폴더에서 파일을 찾는다. #include "파일이름" // 컴파일러 오류 메시지를 발생. #error // 파일을 추가한다. #import // Else if #elif // Else #else // 식별자가 정의되어 있지 않으면 참. #ifndef // 식별자가 정의되어 있으면 참. #ifdef // #findef나 #ifdef, #else에 대한 전처리기 부분을 종료 #endif // 내부 행 넘버를 변경한다. #line // 식별자를 정의하지 않는다. #undef // 컴퓨터 또는 운영 체제 관련 컴파일러 기능을 지정 // #pragma once 처럼 뒤에 토큰을 붙여서 쓰며 토큰들은 아래 링크 참조 // https://msdn.microsoft.com/ko-kr/library/d9x1s805.aspx #pragma // 식별자 또는 매개 변수화된 식별자와 토큰 문자열을 연계한 매크로를 생성 #define

[C] 서식 변환 문자열

https://learn.microsoft.com/ko-kr/cpp/c-runtime-library/format-specification-syntax-printf-and-wprintf-functions?view=msvc-170 https://msdn.microsoft.com/ko-kr/library/56e442dc.aspx https://msdn.microsoft.com/ko-kr/library/hf4y5e3w.aspx 출력 형식 설명 %d 10진수 정수형으로 출력합니다. %o (%#o) 8진수 정수형으로 출력합니다. %x (%#x) 16진수 정수형으로 출력합니다. %X 16진수 정수형 대문자로 출력합니다. %p 16진수 정수형으로 출력, 4byte 모두 출력 값이 입력되지 않은 앞 부분은 0으로 채워짐 %u 부호없는 10진수 정수형으로 출력합니다. %c 한 문자를 출력합니다. %s 문자열을 출력합니다. %f 부동소수점으로 12.345와 같이 출력합니다. %e 부동소수점으로 1.2345E12와 같은 형식으로 출력합니다. %E %e와 같되 대문자로 출력 %g %e나 %f 중에서 출력할 자릿수를 덜 차지하는 형태로 출력합니다. %G %g와 같되 대문자로 출력 %i %d와 같음 %% % 출력

[C] 난수 생성

#include <stdio.h> #include <time.h> srand((unsigned int)time(NULL)); // 이 코드는 함수에 한번만 써주면 됨 num = rand() % 100 ; // 0~99의 난수를 생성 num = rand() % 10; // 0~9의 난수를 생성

[C] 시간 지연

// windows.h 헤더 파일 필요. #include <windows.h> // 시간 단위는 ms. Sleep(1000); // Sleep(1000);은 1초 Sleep(10000); // Sleep(10000);은 10초

[C] __int64

#include <stdio.h> int main(int argc, char *argv[], char **env) { __int64 temp; fputs("숫자를 입력해 주세요 : ", stdout); scanf("%I64d", &a); // %I64d 에서 64 앞에 소문자 l(엘)이 아니라 대문자 I(아이) printf("입력한 숫자는 : \n%I64d\n", temp); return 0; } 약 9220000000000000000 (922경)의 숫자까지 인식

[C] 값 입력할 때마다 메모리 할당

#include <cstdio> #include <cstdlib> #include <malloc.h> int *temp, i = 0; void test(int input); int main() { int input = 0; while(1) { printf("입력하세요 : "); scanf("%d", &input); test(input); } return 0; } void test(int input) { i += 1; temp = (int *)realloc(temp, sizeof(int) * i); temp[i - 1] = input; for(int j = 0; j <= i - 1; j++) { printf("res = %d\n", temp[j]); } // 이렇게 할 경우 배열의 경우 배열의 크기가 나오지만 포인터 변수로 // 동적 할당 했을 경우 포인터 변수의 크기가 나옴. printf("sizeof를 사용한 크기 측정 : %d\n", sizeof(temp)); // 동적 할당된 메모리의 크기를 확인하려면 _msize 함수를 사용해야 함... // _msize 함수를 사용하기 위해선 malloc.h를 include 해야 함 printf("_msize를 사용한 크기 측정 : %d\n\n", _msize(temp)); }

[C] 2차원 배열 동적 할당

#define ROW 3 #define COL 4 char **ptr = NULL; ptr = (char**)malloc(sizeof(char*) * ROW); // 포인터 배열 개수 (행의 개수) *ptr = (char*)malloc(sizeof(char) * (ROW * COL)); // 2차원 배열 총 개수 for(i = 1; i < ROW; i++){ // i=1부터 하면 됩니다. ptr[0]은 *ptr과 같기 때문에 ptr[i] = ptr[i-1] + COL; // 4(COL) 는 열의 개수입니다 } // 해제 free(*ptr); free(ptr);

[C] 소문자는 대문자로 대문자는 소문자로

#include <stdio.h> #include <string.h> #include <ctype.h> int UpperLower(char *temp); int main() { char strtest[10] = {0}; strcpy(strtest, "aBcDeF!@#"); printf("Orinal Str - %s\n\n", strtest); UpperLower(strtest); printf("UpperLower - %s\n\n", strtest);  return 0; } int UpperLower(char *temp) { for( ; *temp != NULL; temp++) { if(isalpha(*temp)) { *temp = *temp ^ 0x20; } } return 0; }