** 배열의 이름을 대상으로 하는 sizeof 연산의 결과로는 바이트 단위의 배열 크기가 반환된다.
** 널(NULL) 문자의 아스키 코드 값은 0이다.
그리고 이를 문자의 형태로 출력할 경우, 아무런 출력이 발생하지 않는다.
** C 언어에서 표현하는 모든 문자열의 끝에는 널 문자가 자동으로 삽입된다.
** 메모리 상에서 문자열을 이진 데이터로 저장하기 때문에
문자열의 시작과 끝이 표시되어 있지 않다면, 문자열을 구분하는 것은 불가능
** 포인터 변수란 메모리의 주소 값을 저장하기 위한 변수
ㄴ 포인터변수 = 변수 형태의 포인터 + 상수 형태의 포인터
** 포인터형(type)
: 포인터 변수의 선언 및 구분에 사용
** &
: 피연산자의 주소값을 반환하는 연산자
** *
: 포인터가 가리키는 메모리는 참조하는 연산자
** 포인터의 형이 존재하는 이유는 포인터 기반의 메모리 접근기준을 마련하기 위함이다.
포인터에 형이 존재하지 않는다면 * 연산을 통한 메모리 접근이 불가능한다.
** 잘못된 포인터 사용과 해결책
예1) 초기화 안함 → 쓰레기 값으로 초기화
예2) 임의의 값을 넣음 → 임의의 값이 어디인지 알고 초기화를 하는가?
결국, 쓰레기값 초기화와 다를 바가 없음
=> 포인터 변수를 우선 선언만 해놓고 이후에 유효한 주소 값을 채워 넣을 생각이라면,
널(NULL) 포인터로 초기화
ㄴ 아무데도 가리키지 않는다!
ㄴ 따라서, 이를 이용한 * 연산은 메모리 공간에 어떠한 영향도 미치지 않음
비록 에러는 나지만,
잘못된 메모리 접근에 대해 보호장치가 없는 운영체제에서도 시스템에 치명적인 영향을 끼지지 않음
** 배열의 이름은 상수 형태의 포인터
포인터 변수 | 배열의 이름(포인터 상수) | |
이름이 존재? | 존재 | 존재 |
무엇을 저장? | 메모리 주소 값 | 메모리 주소 값 |
주소의 값 변경 가능? | 가능 | 불가능 |
** arr[i] == *(arr + 1)
** 배열을 기반으로 하는 변수 형태의 문자열 : 변경 가능,
포인터 기반으로 하는 상수 형태의 문자열 : 변경 불가능
=> 배열이름 str1은 계속해서 str1[0]에 저장된 문자 M이 가리키는 상태이어야 함
하지만, 포인터 변수 str2는 다른 위치를 가리킬 수 있음
https://dojang.io/mod/page/view.php?id=328
https://dphater.tistory.com/entry/18C%EC%96%B8%EC%96%B4-%EB%AC%B8%EC%9E%90%EC%97%B4
https://m.blog.naver.com/dlscjs8646/222166081854
** 포인터 배열 : 포인터 변수로 이뤄진, 그래서 주소 값의 저장이 가능한 배열
** 문자열 배열 : 문자열의 주소 값을 저장할 수 있는 배열
ㄴ char형 포인터 배열은 문자열의 주소 값을 저장할 수 있는 배열이다 보니 문자열 배열이라고 부름
** 큰따옴표로 묶어서 표현되는 문자열은 그 형태와 상관없이 메모리 공간에 저장되고,
그 위치에 저장된 문자열의 주소값이 반환됨
** 인자전달의 기본 방식은 값의 복사
ㄴ 즉, 함수 호출시 전달되는 인자의 값은 매개변수에 복사
** 값을 전달하는 형태의 함수 호출 : Call-by-value
** 주소 값을 전달하는 형태의 함수 호출 : Call-by-reference
** const는 변수를 상수화하는 목적도 있지만, 포인터 변수를 대상으로도 선언 가능
ㄴ 포인터 변수가 참조하는 대상의 변경을 허용하지 않는 const 선언을 할 수 있음
** 도전 프로그래밍2
1.
#include <stdio.h>
void PrintOddNum(const int* ptr, const int size)
{
printf("Odd : ");
for (int i = 0; i < size; i++)
{
if (*(ptr + i) % 2 == 1)
printf("%d ", *(ptr + i));
}
printf("\n");
}
void PrintEvenNum(const int* ptr, const int size)
{
printf("Even : ");
for (int i = 0; i < size; i++)
{
if (*(ptr + i) % 2 == 0)
printf("%d ", *(ptr + i));
}
printf("\n");
}
int main(void)
{
int num[10];
printf("Enter a total of 10 numbers\n");
for (int i = 0; i < sizeof(num) / sizeof(int); i++)
{
printf("input : ");
scanf("%d", &num[i]);
}
printf("\n");
PrintOddNum(num, sizeof(num) / sizeof(int));
PrintEvenNum(num, sizeof(num) / sizeof(int));
return 0;
}
2.
#include <stdio.h>
int main(void)
{
int num;
int size = 0;
int result[100];
printf("Enter Decimal integers : ");
scanf("%d", &num);
while (num > 0)
{
const int remainder = num % 2;
num /= 2;
result[size] = remainder;
size += 1;
}
printf("\n");
for (int i = size - 1; i >= 0; i--)
{
printf("%d", result[i]);
}
return 0;
}
3.
#include <stdio.h>
int main(void)
{
int num[10];
int result[10];
int front = 0;
int back = 9;
printf("Enter 10 numbers\n");
for (int i = 0; i < 10; i++)
{
printf("intput : ");
scanf("%d", &num[i]);
}
for (int i = 0; i < sizeof(num) / sizeof(int); i++)
{
if (num[i] % 2 == 0)
{
result[back] = num[i];
back -= 1;
}
else
{
result[front] = num[i];
front += 1;
}
}
printf("\n");
printf("Output of elements in an array : ");
for (int i = 0; i < sizeof(num) / sizeof(int); i++)
{
printf("%d ", result[i]);
}
return 0;
}
4.
#include <stdio.h>
void CheckPalindrome(const char inputString[])
{
int size = 0;
while (inputString[size] != 0)
{
size += 1;
}
int front = 0;
for (int back = size - 1; back >= 0; back--)
{
if (inputString[front] != inputString[back])
{
printf("Not Palindrome");
return;
}
front += 1;
}
printf("Palindrome");
}
int main(void)
{
char inputString[100];
printf("Input String : ");
scanf("%s", inputString);
CheckPalindrome(inputString);
return 0;
}
▼ string.h에 선언되어 있는 strlen 이란 함수 이용
#include <stdio.h>
#include <string.h>
void CheckPalindrome(const char inputString[])
{
const int size = strlen(inputString);
int front = 0;
for (int back = size - 1; back >= 0; back--)
{
if (inputString[front] != inputString[back])
{
printf("Not Palindrome");
return;
}
front += 1;
}
printf("Palindrome");
}
int main(void)
{
char inputString[100];
printf("Input String : ");
scanf("%s", inputString);
CheckPalindrome(inputString);
return 0;
}
5.
#include <stdio.h>
int main(void)
{
int data[] = {3, 2, 4, 1};
const int size = sizeof(data) / sizeof(int);
int first = 0;
int second = 1;
int endIdx = size - 1;
while (1) {
printf("%d %d / ", first, second);
if (data[first] > data[second])
{
const int temp = data[first];
data[first] = data[second];
data[second] = temp;
}
if (endIdx < 2)
break;
if (second < endIdx)
{
first += 1;
second += 1;
}
else
{
first = 0;
second = 1;
endIdx -= 1;
printf("\n");
}
}
printf("\n\n");
for (int i = 0; i < size; i++)
{
printf("%d ", data[i]);
}
return 0;
}
▼ 책 버블 정렬
#include <stdio.h>
void BubbleSort(int ary[], int len) {
for (int i = 0; i < len - 1; i++) {
for (int j = 0; j < len - i - 1; j++) {
if (ary[j] > ary[j + 1]) {
const int temp = ary[j];
ary[j] = ary[j + 1];
ary[j + 1] = temp;
}
}
}
}
int main(void)
{
int data[] = {3, 2, 4, 1};
const int size = sizeof(data) / sizeof(int);
BubbleSort(data, size);
for (int i = 0; i < size; i++)
printf("%d ", data[i]);
return 0;
}
** 해당 글은 윤성우의 열혈 C프로그래밍 도서를 읽고 정리한 글입니다.
'IT공부 > IT서적' 카테고리의 다른 글
[윤성우 열혈 C++프로그래밍] Part2. 객체지향의 도입 (0) | 2024.08.15 |
---|---|
[윤성우 열혈 C++프로그래밍] Part1. c++로의 전환 (0) | 2024.08.08 |
[윤성우 열혈 C프로그래밍] Part4. C언어의 깊은 이해 (0) | 2024.07.28 |
[윤성우 열혈 C프로그래밍] Part3. 포인터와 배열의 완성 (0) | 2024.07.24 |
[윤성우 열혈 C프로그래밍] Part1. C 언어의 기본 (0) | 2024.07.16 |