Notion link : https://melon-taker-d3e.notion.site/3-1-90e463fb742f4326a8388aa75030a64c
| 자료형 | 범위 |
|---|---|
| bool | true 또는 false |
| char | -128 ~ 127 |
| short | -32,768 ~ 32,767 |
| int | -2,147,483,648 ~ 2,147,483,647 |
| long long | -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 |
| float | 1.2 x 10^-38 ~ 3.4 x 10^38 |
| double | 2.2 x 10^-308 ~ 1.8 x 10^308 |
sizeof 연산자는 변수 또는 데이터 유형의 크기를 바이트 단위로 결정하는 데 사용됩니다. 이는 int, double, float, char와 같은 기본 데이터 유형뿐만 아니라 구조체와 클래스와 같은 사용자 정의 데이터 유형과 함께 사용할 수 있습니다.
다음 예제 코드는 구조체와 sizeof 연산자를 사용하여 구조체의 크기와 멤버 변수의 크기를 계산합니다.
#include <stdio.h>
struct person {
char name[50];
int age;
float height;
};
int main() {
struct person p1;
printf("The size of the person struct is %d bytes\\\\\\\\n", sizeof(struct person));
printf("The size of the name member variable is %d bytes\\\\\\\\n", sizeof(p1.name));
printf("The size of the age member variable is %d bytes\\\\\\\\n", sizeof(p1.age));
printf("The size of the height member variable is %d bytes\\\\\\\\n", sizeof(p1.height));
return 0;
}
위 코드를 실행하면 다음 출력이 표시됩니다.
The size of the person struct is 58 bytes
The size of the name member variable is 50 bytes
The size of the age member variable is 4 bytes
The size of the height member variable is 4 bytes
위 코드에서 person 구조체는 58 바이트 크기이며 name 멤버 변수는 50 바이트이며 age 및 height 멤버 변수는 각각 4 바이트 크기입니다.
sizeof 연산자의 구문은 다음과 같습니다.
sizeof(type);
여기서 type은 유효한 데이터 유형 또는 변수가 될 수 있습니다.
예를 들어 정수 변수의 크기를 바이트 단위로 찾으려면 다음 문을 사용할 수 있습니다.
printf("The size of an integer variable is %d bytes", sizeof(int));
이는 대부분의 현대적인 시스템에서 정수 변수의 크기를 일반적으로 4 바이트로 출력합니다.
sizeof 연산자는 부호 없는 정수형 size_t의 값으로 반환됨에 유의하세요.
size_t 유형은 부호 없는 정수를 저장하는 데 사용되는 데이터 유형입니다. 이는 sizeof 연산자와 같은 목적으로 사용됩니다. size_t는 시스템에 따라 크기가 다르며 일반적으로 unsigned int와 동등합니다. 데이터 유형의 크기가 양수인 경우에 사용하기 적합합니다.
#include <stdio.h>
int main() {
unsigned int a = 4294967295;
int b = -1;
printf("unsigned a = %u, signed b = %d\\\\n", a, b);
printf("unsigned a = %d, signed b = %d\\\\n", a, b);
return 0;
}
Output:
unsigned a = 4294967295, signed b = -1
unsigned a = -1, signed b = -1
이 코드는 unsigned int와 int 자료형을 사용하여 변수 a와 b를 선언합니다. a에는 4294967295를 할당하고, b에는 -1을 할당합니다. 첫 번째 printf 문은 a와 b를 %u와 %d 변환 문자와 함께 출력합니다. 두 번째 printf 문은 a와 b를 둘 다 %d 변환 문자와 함께 출력하고 있습니다.
%u를 사용하여 unsigned int 변수를 출력할 때는 부호 없는 값으로 출력됩니다. 이는 %d를 사용하여 출력할 때와는 달리 값의 부호가 없기 때문입니다. 따라서 첫 번째 printf 문은 a의 값을 올바르게 출력합니다. 그러나 b는 부호 있는 변수이므로 -1을 출력합니다.
두 번째 printf 문에서 %d 변환 문자를 사용하여 a를 출력하면, 부호있는 int 변수로 간주되어 값이 부호화됩니다. a의 값이 4294967295이므로 이것은 부호화 된 int 값의 최대 값 2147483647보다 큽니다. 이는 정수 오버플로우를 일으키고, 이것이 부호화된 값 -1로 해석되어 출력된 이유입니다.
| 자료형 | 크기 (byte) |
|---|---|
| float | 4 |
| double | 8 |
| long double | 16 |
다음은 유효숫자를 파악하는 코드입니다.
#include <stdio.h>
int main() {
float f = 12345.67890123456789;
double d = 12345.67890123456789;
printf("float 유효숫자: %.20f\\n", f);
printf("double 유효숫자: %.20lf\\n", d);
return 0;
}
출력값:
float 유효숫자: 12345.67871093750000000
double 유효숫자: 12345.67890123456789000
초기값과 출력값이 다른 이유는 float과 double이 표현할 수 있는 범위와 정밀도가 다르기 때문입니다. float은 4바이트(32비트)이며, double은 8바이트(64비트)입니다. float은 약 7자리의 유효숫자를 가지며, double은 약 16자리의 유효숫자를 가집니다. 따라서 float에서는 12345.67890123456789라는 값을 정확하게 표현할 수 없으므로 근사치인 12345.67871093750000000으로 출력됩니다. 반면 double은 12345.67890123456789라는 값을 정확하게 표현할 수 있으므로, 초기값과 출력값이 같습니다..
IEEE 754 부동소수점 방식으로 표현했을 경우, 23자리까지 유효 비트이며, 2의 23승은 10의 7승과 유사하기 때문에 십진수 경우 7자리까지 유효 숫자입니다.
#include <stdio.h>
int main() {
double d = 0.1;
printf("double 저장값: %.20lf\\n", d);
return 0;
}
위 코드를 실행하면 다음과 같은 출력이 나타납니다.
double 저장값: 0.10000000000000000555
float과 double 부동소수점 방식으로 12345.67890123456789을 표현하면 다음과 같습니다.
| 자료형 | 부호비트 | 지수비트 | 가수비트 |
|---|---|---|---|
| float | 0 | 10000011 | 00111100000011010001110 |
| double | 0 | 10000000010 | 0011110000001101000111001011000111110101110000100111 |
char 배열명[문자열길이+1]=문자열;
\\0)를 추가해야 합니다. 이는 문자열의 끝을 표시하는 특별한 문자입니다. null 문자를 빠뜨리면 문자열을 처리하는 함수가 제대로 동작하지 않을 수 있습니다. 예를 들어, 다음 코드에서는 문자열 str을 출력할 때 null 문자를 빠뜨렸기 때문에 예상치 못한 결과를 출력합니다.#include <stdio.h>
int main() {
char str[5] = "hello";
printf("%s", str);
return 0;
}
출력값:hellorv▒
위 코드에서 str 배열의 크기는 5이므로, 문자열 "hello"와 null 문자(\0)를 모두 저장할 수 있는 크기입니다. 그러나 null 문자(\0)를 생략하고 문자열을 출력하면 예상치 못한 결과가 출력됩니다. 따라서 문자열을 저장할 때는 null 문자(\0)를 반드시 추가해야 합니다.char str[6] = "hello";
위 코드에서는 문자열 "hello"와 null 문자(\\0)를 모두 저장할 수 있도록 배열의 크기를 6으로 지정하였습니다.#include <stdio.h>
int main() {
char str[6] = "hello";
printf("%s", str);
return 0;
}
Output:
hello
C 언어에서 새로운 문자열을 배열에 저장하는 방법은 memcpy()와 strcpy() 함수를 사용하는 것입니다.
memcpy()memcpy() 함수는 메모리 영역을 복사하는 데 사용됩니다. 아래 예시는 memcpy() 함수를 사용하여 문자열을 배열에 복사하는 코드입니다.
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, world!";
char dest[20];
memcpy(dest, src, strlen(src) + 1);
printf("src: %s\\\\\\\\\\\\\\\\n", src);
printf("dest: %s\\\\\\\\\\\\\\\\n", dest);
return 0;
}
src 배열에 문자열 "Hello, world!"를 저장하고, dest 배열에 src 배열의 내용을 memcpy() 함수를 사용하여 복사합니다. strlen() 함수는 문자열의 길이를 반환하며, + 1은 NULL 문자를 포함하기 위한 것입니다.
strcpy()strcpy() 함수는 문자열을 복사하는 데 사용됩니다. 아래 예시는 strcpy() 함수를 사용하여 문자열을 배열에 복사하는 코드입니다.
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, world!";
char dest[20];
strcpy(dest, src);
printf("src: %s\\\\\\\\\\\\\\\\n", src);
printf("dest: %s\\\\\\\\\\\\\\\\n", dest);
return 0;
}
src 배열에 문자열 "Hello, world!"를 저장하고, dest 배열에 src 배열의 내용을 strcpy() 함수를 사용하여 복사합니다.
memcpy()와 strcpy() 함수 모두 src 배열의 내용을 dest 배열에 복사합니다. 하지만 둘의 차이점은 NULL 문자 처리에 있습니다. memcpy() 함수는 NULL 문자를 복사하지 않습니다. 따라서 복사된 문자열이 정확한 문자열인지 확인하려면 NULL 문자를 수동으로 추가해야 합니다. 반면 strcpy() 함수는 NULL 문자를 복사하므로 추가 작업이 필요하지 않습니다.
문자열을 저장할 때 null 문자(\\\\\\\\0)를 생략하면 문자열을 처리하는 함수가 제대로 동작하지 않을 수 있습니다. 예를 들어, 다음 코드에서는 문자열 str을 출력할 때 null 문자를 빠뜨렸기 때문에 예상치 못한 결과를 출력합니다.
#include <stdio.h>
int main() {
char str[5] = "hello";
printf("%s", str);
return 0;
}
출력값:
hellorv▒
str 배열의 크기는 5이므로, 문자열 "hello"와 null 문자(\\0)를 모두 저장할 수 있는 크기입니다. 그러나 null 문자(\\0)를 생략하고 문자열을 출력하면 예상치 못한 결과가 출력됩니다. 따라서 문자열을 저장할 때는 null 문자(\\0)를 반드시 추가해야 합니다.
const 키워드를 사용하여 상수를 선언할 수 있습니다. 상수는 한 번 정해지면 값을 변경할 수 없습니다.const int a = 100;
const 키워드를 사용하여 변수를 선언하면, 해당 변수는 읽기 전용이 됩니다. 따라서 값을 변경하려고 하면 컴파일러가 오류를 발생시킵니다.const int a = 100;
a = 200; // 컴파일 오류 발생
const 키워드를 사용하여 함수 매개변수를 선언하면, 해당 매개변수에 전달되는 값이 변경되지 않도록 보장할 수 있습니다.void print(const char* str) {
printf("%s", str);
}
int main() {
char* s = "hello";
print(s);
return 0;
}
첫번째 방법은 변수를 선언하면서 값을 할당하는 것입니다.
const int a = 100;
두 번째 방법은 변수를 선언하고, 나중에 값을 할당하는 것입니다. 이때는 const 키워드 앞에 extern 키워드를 사용하여 선언합니다.
// const.h
extern const int a;
// const.c
#include "const.h"
const int a = 100;
// main.c
#include "const.h"
int main() {
printf("%d", a);
return 0;
}
const 키워드를 사용하면, 변수의 값을 변경할 수 없다는 것을 명시적으로 나타낼 수 있습니다. 이는 코드의 가독성을 높이고, 프로그램의 안정성을 높입니다.
다음은 const 변수를 사용하여 간단한 소스 코드 예시입니다. 변수 a를 const로 선언하고, a 값을 출력하는 코드입니다.
#include <stdio.h>
int main() {
const int a = 100;
printf("%d", a);
return 0;
}
출력 결과:
100
정수형과 실수형 데이터형의 종류, 크기, 값의 저장 범위, 출력 및 변환 문자에 대한 표입니다.
| 데이터형 | 종류 | 크기 (바이트) | 값의 저장 범위 | 변환문자 |
|---|---|---|---|---|
| char | 부호 있는 정수형 | 1 | -128 ~ 127 | %c %d |
| unsigned char | 부호 없는 정수형 | 1 | 0 ~ 255 | %u |
| short | 부호 있는 정수형 | 2 | -32,768 ~ 32,767 | %d |
| unsigned short | 부호 없는 정수형 | 2 | 0 ~ 65,535 | %u |
| int | 부호 있는 정수형 | 4 | -2,147,483,648 ~ 2,147,483,647 | %d |
| unsigned int | 부호 없는 정수형 | 4 | 0 ~ 4,294,967,295 | %u |
| long | 부호 있는 정수형 | 4 | -2,147,483,648 ~ 2,147,483,647 | %ld |
| unsigned long | 부호 없는 정수형 | 4 | 0 ~ 4,294,967,295 | %lu |
| long long | 부호 있는 정수형 | 8 | -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 | %lld |
| unsigned long long | 부호 없는 정수형 | 8 | 0 ~ 18,446,744,073,709,551,615 | %llu |
| float | 실수형 | 4 | 1.2E-38 ~ 3.4E+38 | %f |
| double | 실수형 | 8 | 2.2E-308 ~ 1.8E+308 | %lf |
| long double | 실수형 | 12 | 3.4E-4932 ~ 1.1E+4932 | %Lf |