검색결과 리스트
언어/C에 해당되는 글 11건
- 2018.12.30 [C] 문자열 유사클래스 구현
- 2018.12.30 [C] Q: 스택의 사이즈는 왜이렇게 작나요?
- 2018.12.30 [C] ()와 (void)의 차이
- 2018.12.30 [C] Q: scanf에서 오류가 나요. in Visual Studio
- 2018.12.30 [C] C99~C11 조금 낯선 기능들
- 2018.12.30 [C] Q: 프로그램이 실행되자마자 꺼져요!
- 2018.12.17 [C] 함수 호출 규약.link
- 2018.12.17 [C] 쇼트 서킷으로 조건문 구현
글
[C] 문자열 유사클래스 구현
oop 흉내.
C의 한계로, 메서드마다 첫번째 인자로 객체 자신의 주소를 보내줘야 함.
https://github.com/myyrakle/c-oop-string/blob/master/main.c
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 | #include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdarg.h> //기본 초기화 목록입니다. //기본 빈 값을 넣어주고, //유사 멤버함수들을 전부 넣어줍니다. #define NullString \ { \ NULL, 0, \ _string_set, \ _string_setn, \ _string_gets, \ _string_get_length, \ _string_copy_from, \ _string_clone, \ _string_move, \ _string_append, \ _string_append_raw, \ _string_swap, \ _string_clear, \ _string_is_empty, \ _string_compare, \ _string_compare_raw, \ _string_is_same, \ _string_is_same_raw, \ _string_format, \ _string_append_format, \ _string_at, \ _string_ptr_at, \ _string_findc, \ _string_finds, \ _string_finds_raw, \ } //C스타일 문자열 유사클래스입니다. struct String { char* data; size_t length; //문자열을 할당합니다. void (*set)(struct String*, const char*); void (*setn)(struct String*, const char*, size_t); //문자열을 가져옵니다. const char* (*gets)(const struct String*); //문자열의 길이를 가져옵니다. size_t (*get_length)(const struct String*); //깊은복사를 행합니다. void (*copy_from)(struct String*, const struct String*); //깊게 복제된 객체를 반환합니다. struct String (*clone)(const struct String*); //이동합니다. 자신은 clear가 됩니다. struct String (*move)(struct String*); //이어붙입니다. void (*append)(struct String*, const struct String*); //String 버전입니다. void (*append_raw)(struct String*, const char*); //생 문자열 버전입니다. //교환합니다. void (*swap)(struct String*, struct String*); //지워버립니다. void (*clear)(struct String*); //비어있는지 여부를 확인합니다. int (*is_empty)(const struct String*); //비교해서 같으면 0... 뭐 그런거요 int (*compare)(const struct String*, const struct String*); //String 버전입니다. int (*compare_raw)(const struct String*, const char*); //생 문자열 버전입니다. //같으면 1. 다르면 0. int (*is_same)(const struct String*, const struct String*); //String 버전입니다. int (*is_same_raw)(const struct String*, const char*); //생 문자열 버전입니다. //포맷팅합니다. void (*format)(struct String*, const char*, ...); //포맷팅해서 그대로 대입합니다. void (*append_format)(struct String*, const char*, ...); //포맷팅한 문자열을 이어붙입니다. //인덱싱합니다. 범위를 벗어나면 EOF를 줘요. int (*at)(const struct String*, size_t); //그냥 그 문자를 반환합니다. int* (*ptr_at)(struct String*, size_t); //그 문자의 주소를 반환합니다. //문자나 문자열을 탐색해서 인덱스를 줍니다. //못찾으면 EOF를 반환합니다. int (*findc)(const struct String*, char c); //문자를 찾습니다. int (*finds)(const struct String*, const struct String*); //String 문자열을 찾습니다. int (*finds_raw)(const struct String*, const char*); //생 문자열을 받아서 찾습니다. }; typedef struct String String; typedef String string; /*빌더 함수 선언*/ String make_string(const char*); String make_nullstring(); /*String 유사메서드*/ void _string_set(String*, const char*); void _string_setn(String*, const char*, size_t); const char* _string_gets(const String*); size_t _string_get_length(const String*); void _string_copy_from(String* self, const String* other); String _string_clone(const String* self); String _string_move(String* self); void _string_append(String* self, const String* other); void _string_append_raw(String* self, const char* other); void _string_swap(String* self, String* other); void _string_clear(String* self); int _string_is_empty(const String* self); int _string_compare(const String* self, const String* other); int _string_compare_raw(const String* self, const char* other); int _string_is_same(const String* self, const String* other); int _string_is_same_raw(const String* self, const char* other); void _string_format(String* self, const char* format,...); void _string_append_format(String* self, const char* format, ...); int _string_at(const String* self, size_t index); int _string_ptr_at(String* self, size_t index); int _string_findc(const String* self, char c); int _string_finds(const String* self, const String* key); int _string_finds_raw(const String* self, const char* key); /*유사메서드 정의*/ void _string_set(String* self, const char* s) { self->length = strlen(s); free(self->data); self->data = malloc(sizeof(char)*self->length +1); strncpy(self->data, s, self->length+1); } void _string_setn(String* self, const char* s, size_t len) { self->length = len; free(self->data); self->data = malloc(sizeof(char)*self->length +1); strncpy(self->data, s, self->length +1); } const char* _string_gets(const String* self) { return self->data; } size_t _string_get_length(const String* self) { return self->length; } void _string_copy_from(String* self, const String* other) { self->length = other->length; free(self->data); self->data = malloc(sizeof(char)*self->length +1); strncpy(self->data, other->data, self->length +1); } String _string_clone(const String* self) { String temp = make_nullstring(); temp.setn(&temp, self->data, self->length); return temp; } String _string_move(String* self) { String temp = make_nullstring(); temp.data = self->data; temp.length = self->length; self->data=NULL; self->length=0; return temp; } void _string_append(String* self, const String* other) { self->length+=other->length; realloc(self->data, self->length+1); strncat(self->data, other->data, self->length+1); } void _string_append_raw(String* self, const char* other) { self->length+=strlen(other); realloc(self->data, self->length); strncat(self->data, other, self->length+1); } void _string_swap(String* self, String* other) { char* t = self->data; size_t t2 = self->length; self->data = other->data; self->length = other->length; other->data = t; other->length = t2; } void _string_clear(String* self) { self->length=0; free(self->data); self->data=NULL; } int _string_is_empty(const String* self) { return self->data==NULL; } int _string_compare(const String* self, const String* other) { return strcmp(self->data, other->data); } int _string_compare_raw(const String* self, const char* other) { return strcmp(self->data, other); } int _string_is_same(const String* self, const String* other) { return strcmp(self->data, other->data)==0; } int _string_is_same_raw(const String* self, const char* other) { return strcmp(self->data, other)==0; } enum { STRING_BUFFER_SIZE = 200 //포맷팅 함수에서 사용할 버퍼 크기. 늘려도 됨 }; void _string_format(String* self, const char* format,...) { char buffer[STRING_BUFFER_SIZE]; va_list args; va_start(args, format); vsprintf(buffer, format, args); self->set(&self, buffer); va_end(args); } void _string_append_format(String* self, const char* format, ...) { char buffer[STRING_BUFFER_SIZE]; va_list args; va_start(args, format); vsprintf(buffer, format, args); self->append_raw(&self, buffer); va_end(args); } int _string_at(const String* self, size_t index) { if(index<0 || index>=self->length) return EOF; else return self->data[index]; } int _string_ptr_at(String* self, size_t index) { if(index<0 || index>=self->length) return EOF; else return &(self->data[index]); } int _string_findc(const String* self, char c) { for(int i=0; i<self->length; ++i) { if(self->data[i]==c) return i; } return EOF; } int _string_finds(const String* self, const String* key) { const char* finded = strstr(self->data, key->data); if(finded==NULL) return EOF; else return (int)finded - (int)(self->data); } int _string_finds_raw(const String* self, const char* key) { const char* finded = strstr(self->data, key); if(finded==NULL) return EOF; else return (int)finded - (int)(self->data); } //String 유사클래스 유사객체를 생성해서 반환합니다. String make_string(const char* s) { String temp = NullString; temp.set(&temp, s); return temp; } //빈 유사객체를 생성해서 반환합니다. String make_nullstring() { String temp = NullString; return temp; } const int main(void) { string s = make_string("hello"); printf(s.data); return 0; } | cs |
'언어 > C' 카테고리의 다른 글
[C] Q: 스택의 사이즈는 왜이렇게 작나요? (0) | 2018.12.30 |
---|---|
[C] ()와 (void)의 차이 (0) | 2018.12.30 |
[C] Q: scanf에서 오류가 나요. in Visual Studio (0) | 2018.12.30 |
[C] C99~C11 조금 낯선 기능들 (0) | 2018.12.30 |
[C] Q: 프로그램이 실행되자마자 꺼져요! (0) | 2018.12.30 |
글
[C] Q: 스택의 사이즈는 왜이렇게 작나요?
Q: When you allocate memory on the heap, the only limit is free RAM (or virtual memory).
힙에 메모리를 할당할 때는 램이나 가상메모리의 크기 내에서는 자유롭게 사이즈를 줄 수 있죠.
It makes Gb of memory.
그래서 보통 기가바이트 단위도 쓸 수가 있어요.
그런데 스택은 왜이렇게 작은거죠? 보통 1메가정도밖에 안되더라고요.
What technical reason prevents you to create really big objects on the stack ?
기술적인 이유 때문에 스택에 큰 객체를 두지 못하는건가요?
...
A: My intuition is the following.
내 생각엔 이래요.
The stack is not as easy to manage as the heap.
스택은 힙처럼 관리하기가 쉽지 않아요.
The stack need to be stored in continuous memory locations.
스택은 연속적인 메모리 위치에 저장될 필요가 있거든요.
This means that you cannot randomly allocate the stack as needed, but you need to at least reserve virtual addresses for that purpose.
스택에는 필요에 따라 랜덤으로 할당을 할수 없단거죠.
하지만 최소한 가상 주소는 예약을 해놔야 합니다.
The larger the size of the reserved virtual address space, the fewer threads you can create.
예약된 가상 주소 공간이 커질수록 만들수 있는 스레드 수는 적어져요.
예를 들어 32비트 앱은 보통 2기가의 가상주소 공간을 가집니다.
This means that if the stack size is 2MB (as default in pthreads), then you can create a maximum of 1024 threads.
그러니까 스택의 크기가 2메가면 최대 1024개의 스레드를 생성할 수가 있는거죠.
This can be small for applications such as web servers.
웹서버 같은 앱들은 이게 적어도 되는데요.
Increasing the stack size to, say, 100MB (i.e., you reserve 100MB, but do not necessarily allocated 100MB to the stack immediately), would limit the number of threads to about 20, which can be limiting even for simple GUI applications.
스택의 크기를 100으로 늘리면(100메가를 예약해도 바로 100메가를 할당하진 않음), 스레드 수를 20개 정도로 제한할 수 있죠. 이건 간단한 gui 앱에서도 제한이 될수 있어요.
흥미로운 문제는, 64비트 플랫폼에서도 여전히 이 제한이 존재한다는 거에요.
I do not know the answer, but I assume that people are already used to some "stack best practices":
이 문제에 대해서는 답을 드리진 못하겠지만, 아마 사람들이 스택의 그 "무난한 관행"에 익숙해졌기 때문인것 같네요.
be careful to allocate huge objects on the heap and, if needed, manually increase the stack size.
큰 객체는 힙에 놓고 필요할 때만 스택의 크기를 늘리는게 좋다는 겁니다.
Therefore, nobody found it useful to add "huge" stack support on 64-bit platforms.
그래서 64비트 플랫폼에서 어떤 환경도 기본으로 "큰" 스택을 지원하지 않는거에요.
'언어 > C' 카테고리의 다른 글
[C] 문자열 유사클래스 구현 (0) | 2018.12.30 |
---|---|
[C] ()와 (void)의 차이 (0) | 2018.12.30 |
[C] Q: scanf에서 오류가 나요. in Visual Studio (0) | 2018.12.30 |
[C] C99~C11 조금 낯선 기능들 (0) | 2018.12.30 |
[C] Q: 프로그램이 실행되자마자 꺼져요! (0) | 2018.12.30 |
글
[C] ()와 (void)의 차이
그래서 위에서 아래에 있는 함수를 갖다 쓰려면 애가 찾질 못하죠.
그래서 전방선언-프로토타입이란걸 위에다 붙여줍니다. 보통 헤더에 분리해서 넣어주죠.
이렇게요.
자 근데. 선언부의 파라미터를 전부 지우면 어떨까요?
시그너처가 다르니 에러가 날까요?
한번 봅시다.
잘 됩니다.
선언부에서의 빈 ()는 이건 뭐든 들어갈수 있어! 라는 뜻이기 때문이죠."이건 파라미터를 안 받아!"라는 의미를 부여하려면 void를 명시해줍니다.
이제 (void)라고 확실히 명시가 됐으니, 아래에 있는 정의부와 일치하지 않아서 에러가 납니다.
'언어 > C' 카테고리의 다른 글
[C] 문자열 유사클래스 구현 (0) | 2018.12.30 |
---|---|
[C] Q: 스택의 사이즈는 왜이렇게 작나요? (0) | 2018.12.30 |
[C] Q: scanf에서 오류가 나요. in Visual Studio (0) | 2018.12.30 |
[C] C99~C11 조금 낯선 기능들 (0) | 2018.12.30 |
[C] Q: 프로그램이 실행되자마자 꺼져요! (0) | 2018.12.30 |
글
[C] Q: scanf에서 오류가 나요. in Visual Studio
일단 이건 비주얼 스튜디오에서만 해당되는 문제입니다.
입력을 받는 간단한 프로그램을 하나 짜보도록 하죠.
1 2 3 4 5 6 7 8 9 10 11 12 | #include "stdafx.h" #include <iostream> int main() { char buffer[100]; printf("암거나 입력하세요 : "); scanf("%s", buffer); printf("결과 %s", buffer); } | cs |
VS에서는 이렇게 문법적으로 아무런 문제도 없는 코드를 짜도, 문제가 발생할 수 있습니다.
초심자들이 한번씩은 걸려드는 함정이죠.
자 오류가 떴습니다. 근데 대체 뭐라고 하는걸까요?
scanf 함수는 안전하지 않으니까 scanf_s를 쓰라고 하는 겁니다.
근데 그건 니들 생각이고, 나는 그걸 쓰고싶지 않아요.
1.define(안됐는데 알고보니 됨)
어쨌든 scanf를 쓰고싶으면 _CRT_SECURE_NO_WARNINGS라는 매크로를 정의하라고 하는데요. 그럼 이렇게 짜면 됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | #include "stdafx.h" #include <iostream> #define _CRT_SECURE_NO_WARNINGS //잔소리좀 하지 말 int main() { char buffer[100]; printf("암거나 입력하세요 : "); scanf("%s", buffer); printf("결과 %s", buffer); } | cs |
이런 빌어먹을. 그래도 안된다고 합니다. 얘들이 왜이러지? 예전에는 이러면 됐었는데 뭔가 바뀌었나봅니다.
수정) 알고보니 define을 맨 위에 둬야한다네요. 잘못 씀.
2.pragma
다른 매크로를 써보죠, pragma란 것도 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #include "stdafx.h" #include <iostream> #pragma warning(disable:4996) //좀 닥쳐봐 int main() { char buffer[100]; printf("암거나 입력하세요 : "); scanf("%s", buffer); printf("결과 %s", buffer); } | cs |
3.그냥 scanf_s를 쓸까?
근데 저놈들은 이게ㅔ 뭐라고 자꾸 쓰라고 강요를 하는 걸까요?
실제로 scanf에 취약점이 존재하기 때문입니다. 전달받은 변수보다 입력으로 들어오는 값이 더 크면 버퍼오버플로가 발생하는데, 이게 상당히 위험할 수 있거든요.
그래서 더 큰 값이 들어와도 잘라버릴 수 있도록 맨 마지막 인자로 변수의 크기를 넣어줍니다. '너무 커도 이 변수 크기까지만 넣어라!' 라는 뜻이죠.
이렇게요.
1 2 3 4 5 6 7 8 9 10 11 12 13 | #include "stdafx.h" #include <iostream> int main() { char buffer[100]; printf("암거나 입력하세요 : "); scanf_s("%s", buffer, sizeof(buffer)); //이제 됐냐? printf("결과 %s", buffer); } | cs |
잘 됩니다.
근데 사실 _s는 그렇게 좋은 기능만은 아닙니다. 이걸 이렇게 강력하게 지원하는 컴파일러가 사실상 이거밖에 없는데요...
굳이 이걸 쓰지 않아도 취약점을 막을 수 있는 방법이 많기 때문입니다.. 마지막 인자 때문에 추가되는 오버헤드도 있고요.
4.프로젝트 설정
코드에 손을 대고 싶지 않다면, 좀더 근본적으로 문제를 차단할 수도 있습니다.
자꾸 _s 버전 쓰라고 강요하는걸 SDL 체크라고 하는데요. 이걸 꺼버리면 됩니다.
솔루션 탐색기 창에서 프로젝트 파일에 마우스 오른쪽 버튼을 누르고
속성 창으로 들어갑니다.
그리고 C/C++ -> 일반 -> SDL 검사에서 '아니요'를 선택해주시고 확인 누르시면
잘 됩니다.
'언어 > C' 카테고리의 다른 글
[C] Q: 스택의 사이즈는 왜이렇게 작나요? (0) | 2018.12.30 |
---|---|
[C] ()와 (void)의 차이 (0) | 2018.12.30 |
[C] C99~C11 조금 낯선 기능들 (0) | 2018.12.30 |
[C] Q: 프로그램이 실행되자마자 꺼져요! (0) | 2018.12.30 |
[C] 함수 호출 규약.link (0) | 2018.12.17 |
글
[C] C99~C11 조금 낯선 기능들
구조체 리터럴 (C99)
변수명 없이 임시적으로 생성되는 구조체 리터럴을 선언할 수 있다.
(struct 구조체명) { 요소들...}
구조체 지정 초기화 (C99)
멤버를 직접 지정해서 초기화한다.
보다 명시적이고, 순서와 관련없이 대입해 넣을 수 있다.
여기엔 두가지 방법이 있는데,
.과 =을 쓰는 방법이 이것이다.
= { .멤버명 = 대입값, ...};
근데 매번 .을 붙이려면 그것도 꽤 귀찮지 싶다.
그런 이들을 위한 두번째 방법이 있다.
= {멤버명 : 대입값, ...};
Flexible 배열 멤버 (C99)
아래와 같이 길이가 정해지지 않은 구조체 멤버 배열을 사용하는 기능이다.
struct flex_t{
int age;
char name[];
};
여기에는 몇가지 주의사항과 제약사항이 있다.
사실 좀 많이 까다롭다.
일단 위처럼 플렉서블 배열은 맨 뒤에 와야 한다.
그리고 다른 멤버가 하나 이상 있어야 한다.
일반적인 방법으로 사용하지도 못한다. 길이가 없기 때문에 메모리에 그를 위한 공간이 할당되지 않기 때문이다.
위에서 사용한 구조체 리터럴 예제에 플렉서블을 사용하면 에러가 난다.
그럼 어떻게 써야할까?
결국 동적으로 할당해서 써야한다..
게다가 배열의 추가용량까지 써줘야 한다. 이렇게.
그리고 배열의 특성 중 하나인 '길이' 도 없다.
체크불가.
도대체 왜 넣은 기능인지 모르겠다.
불편하기만 하고 쓸모없다.
익명 구조체 (C11)
구조체 안에다가 이름없는 구조체를 사용할 수 있는 기능이다.
내부의 익명 구조체 멤버는 외부의 구조체 멤버와 같이 액세스를 할 수 있다.
사실 이건 별로 쓸모가 없다. 그냥 중괄호 빼고 합쳐버리지.
어쨌든 이렇게 쓸 수 있다.
익명 공용체 (C11)
익명 공용체는 익명 구조체와 동작방식이 유사하다. 하지만 더 쓸모가 있다.
가끔 비트나 메모리 갖고 장난치다보면 구조체에 공용체를 멤버로 집어넣을 때가 있는데,
이러면 접근시 공용체의 이름까지 써야 하기 때문에 호출하기가 굉장히 귀찮아진다.
그럴때 이걸 사용하면 번거로움을 줄일 수 있다.
__Noreturn (C11)
함수가 반환하지 않고 종료가 됨을 명시한다.
대표적으로 프로그램을 종료하는 exit함수가 이것으로 수식을 하고 있다.
근데 뭐 직접 쓸 일은 별로 없을 것 같다.
_Static_assert (C11)
c++의 static_assert와 동일하다.
컴파일타임에 assert를 뱉는다.
첫번째 인자는 논리식을 받아서 참이면 수행하고, 거짓이면 컴파일을 중단하고 두번째 인자의 문자열을 뱉는다.
성공
실패
이중자/삼중자 (C99)
어떤 키보드는 C에서 필수적으로 사용되는 기호들을 제공하지 않기도 한다.
그래서 흔한 기호를 2~3개의 기호를 조합해서 대체할 수 있게끔 이중자와 삼중자라는 것을 제공한다.
삼중자는 ""보다 우선순위가 높지만 이중자는 그렇지 않다.
# => 삼중자: ??= 이중자: %:
[ => 삼중자: ??( 이중자: <:
] => 삼중자: ??) 이중자: :>
{ => 삼중자: ??< 이중자: <%
} => 삼중자: ??> 이중자: %>
\ => 삼중자: ??/
| => 삼중자: ??!
^ => 삼중자: ??`
~ => 삼중자: ??-
인라인 함수 (C99)
키워드는 inline이고 사용방법은 c++과 동일하다.
2018. 8. 31.
'언어 > C' 카테고리의 다른 글
[C] ()와 (void)의 차이 (0) | 2018.12.30 |
---|---|
[C] Q: scanf에서 오류가 나요. in Visual Studio (0) | 2018.12.30 |
[C] Q: 프로그램이 실행되자마자 꺼져요! (0) | 2018.12.30 |
[C] 함수 호출 규약.link (0) | 2018.12.17 |
[C] 쇼트 서킷으로 조건문 구현 (0) | 2018.12.17 |
글
[C] Q: 프로그램이 실행되자마자 꺼져요!
가장 흔한 질문 중 하나인데, 원래 콘솔에서는 할일 다하면 바로 꺼지는 게 맞는 겁니다.
게다가 요즘 컴퓨터는 겁나게 빠르기 때문에 텍스트 처리 정도의 가벼운 작업 정도는 쉬시식 끝내버리죠. 그래서 그냥은 볼 새가 없습니다.
해결법 1 : Visual Studio를 사용중이라면 컨트롤+F5로 실행합니다. 그럼 꺼지지 않습니다.
Clion 같이 자체 콘솔을 내장하는 IDE를 사용하는 것도 좋습니다.
해결법 2 : windows.h헤더의 system함수로, 코드 마지막 부분, return 앞에 system("pause"); 라고 써줍니다.
pause는 좀 멈춰있으라는 커맨드 명령어입니다.
해결법 3: 사실 방법은 많습니다. 그냥 꺼지지 않게만 하면 되기 때문에, return 앞 끝부분에다 비어있는 무한루프를 붙여도 되고, 의미없는 입력함수를 넣어도 됩니다..
이중에 제일 간단한건 getchar(); 입니다.
2018. 8. 27
'언어 > C' 카테고리의 다른 글
[C] Q: scanf에서 오류가 나요. in Visual Studio (0) | 2018.12.30 |
---|---|
[C] C99~C11 조금 낯선 기능들 (0) | 2018.12.30 |
[C] 함수 호출 규약.link (0) | 2018.12.17 |
[C] 쇼트 서킷으로 조건문 구현 (0) | 2018.12.17 |
[C] sizeof 연산자에 대해서 (0) | 2018.12.17 |
글
[C] 함수 호출 규약.link
함수 호출 규약(Function calling convention)
함수 시그너처에서, 리턴타입과 함수명 사이에 붙어서 함수의 작동 방식을 결정하는 것.
사실 대부분의 경우에서는 직접 명시할 필요가 별로 없음
https://ko.m.wikipedia.org/wiki/X86_호출_규약
위키피디아
http://sweeper.egloos.com/m/829514
친절함
http://qufl1999.egloos.com/m/2338204
ㅡ
http://blog.eairship.kr/m/254
ㅡ
결론.
stdcall
대부분의 경우에는 __stdcall이 약간 더 가볍고 빠름.
다른 별칭으로 CALLBACK, WINAPI, PASCAL, APIENTRY 등이 있음
가변인자 사용 불가
cdecl
가변인자를 사용하려면 __cdecl 사용 필요.
다른 별칭으로 WINAPIV 등이 있음
함수 디폴트 설정임
'언어 > C' 카테고리의 다른 글
[C] C99~C11 조금 낯선 기능들 (0) | 2018.12.30 |
---|---|
[C] Q: 프로그램이 실행되자마자 꺼져요! (0) | 2018.12.30 |
[C] 쇼트 서킷으로 조건문 구현 (0) | 2018.12.17 |
[C] sizeof 연산자에 대해서 (0) | 2018.12.17 |
[C] 포인터란? (0) | 2018.12.17 |
글
[C] 쇼트 서킷으로 조건문 구현
보통 조건문을 사용할땐 if 키워드를 사용하곤 한다.
너무 진부하지 않은가?
스위치도 있지만 경우가 좀 다르고
삼항연산자도 나쁘지 않지만 더 세련된 조건문의 대체재가 있다.
바로 쇼트서킷이라 하는 최적화 현상을 이용하는 것이다.
이게 뭐냐면, 가령 && 연산을 한다 쳐보자.
이 연산은 양쪽이 전부 true일 경우에만 true를 반환한다.
그 말인즉 하나라도 false면 무조건 false가 된다는 말이고, &&연산의 앞부분이 false로 판명나면 뒷부분을 무시하고 지나가도록 최적화를 한다.
이게 바로 쇼트서킷이다.
그리고 ||도 마찬가지다. 앞부분이 true면 그냥 넘어간다.
이 현상을 이용해서 우린 더 멋진 분기를 구성해볼수 있다.
이런 식으로
'언어 > C' 카테고리의 다른 글
[C] Q: 프로그램이 실행되자마자 꺼져요! (0) | 2018.12.30 |
---|---|
[C] 함수 호출 규약.link (0) | 2018.12.17 |
[C] sizeof 연산자에 대해서 (0) | 2018.12.17 |
[C] 포인터란? (0) | 2018.12.17 |
[C] C언어 유니코드 사용법 (0) | 2018.12.17 |