오늘도 끄적끄적

느리더라도 꾸준하게

  • 전역 변수(Global Variable)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include <stdio.h>

    int var = 3; // 전역변수

    void add() {
    var++; // 어디서나 접근 가능
    printf("%d\n", var); // 4
    }

    int main() {
    add();
    printf("%d", var); // 4, 값의 유지
    return 0;
    }
  1. 값의 유지
  2. 어디에서든 접근 가능
  3. main 함수 실행 전에, 프로그램이 실행되자 마자 메모리에 할당됨.
  4. 프로그램이 끝나는 순간 메모리에서 해제됨.
  5. 메모리의 Data 영역에 적재됨.
    &nbsp;
    2번의 이유로 인해서 변수의 스코프가 더럽혀진다.
    더럽혀진다는 의미는 변수 이름의 충돌 가능성이 존재하고,
    그로 인해 변수 이름 짓기에 큰 시간을 할애해야 하며,
    변수의 이름이 길어지거나 이상해지는 경우도 존재한다.
    어디서나 접근 가능하기 때문에 실수로 변수의 값이 바뀔 가능성이 존재한다.
    뭐 그렇다고 해서 꼭 안 좋은 것만은 아니기 때문에 적절히 활용하면 된다.
  • 지역 변수(Local Variable)
    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
    #include <stdio.h>

    int var = 3; // 전역변수

    void add() {
    int var = 4;
    var++;
    // 지역 변수의 우선순위가 전역 변수보다 높음.
    printf("%d\n", var); // 5
    }

    int main() {
    { // block scope
    int asdf = 33;
    printf("%d", asdf);
    }
    // printf("%d", asdf); // 스코프를 벗어나서 컴파일 오류가 남.
    add();
    printf("%d\n", var); // 3, 값의 유지가 안 됨.
    int i = 0;
    // 지역 변수 i의 scope 시작
    for(int i=0; i<3; i++) {
    printf("%d ", i); // 0 1 2
    }
    // 지역 변수 i의 scope 끝
    printf("\n%d", i); // 0, 여기서 나온 건 전역 변수 i
    return 0;
    }
  1. 매번 새로운 값 생성, 값의 유지가 안 됨.
  2. 지정된 블록 스코프(제어문, 함수 등등)에서만 접근 가능
  3. 함수가 실행되는 순간마다 메모리에 할당됨.
  4. 함수가 종료되는 순간마다 메모리에서 해제됨.
  5. 메모리의 Stack 영역에 적재됨.
    &nbsp;
    값이 유지되지 않기 때문에 함수를 실행할 때마다 매번 똑같은 값을 써야할 때 쓴다.
    스코프 내에서만 접근 가능하기 때문에 유지보수에 용이하다.
    가능하면 스코프의 범위는 좁은 게 유지보수하기 편하다고 들었다.
더 읽어보기 »

배열

Java에서는 길이가 0인 배열의 선언도 가능하다.
또한 길이는 int 범위의 양의 정수이다.

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
import java.util.Arrays;

public class test2 {
public static void main(String[] args) {
// 둘 다 가능하지만 후자가 C/C++에서 먹히는 스타일이라 이식성이 높다고 생각한다.
int[] num = new int[5];
boolean flag[] = new boolean[5];

// 배열을 초기화하지 않으면 기본값으로 초기화 돼서 나온다.
for(int i=0; i<num.length; i++) System.out.println(num[i]); // 0
for(int i=0; i<flag.length; i++) System.out.println(flag[i]); // false

double num2[] = new double[]{1.1, 4.5}; // 선언과 동시에 초기화.
double num3[] = new double[5]{1.1, 4.5}; // 길이를 지정해주면 오류가 난다.
double num4[] = {1.5, 3.14, 15}; // 선언과 동시에 초기화 할 때는 new 연산자를 뺄 수 있다.

// 선언과 초기화를 따로 할 때는 new 연산자를 써서 할당까지 해주어야 한다.
double num5[];
num5 = new double[]{33.123, 51.792};

// 아래와 같은 경우를 불허한다.
double num6[] = new double[123];
num6 = {123.22, 33};

// 수정할 때는 new 연산자를 써서 새로 만들어줘야한다.
num2 = new double[]{123, 456, 111.33};

// 아래 세 문장은 배열의 길이가 0이다.
int num7[] = new int[]{};
int num8[] = new int[0];
int num9[] = {};

// import java.util.Arrays;
// java 패키지의 utill 패키지의 Arrays 클래스에 있는 toString이라는 메소드를 쓴다.
System.out.println(Arrays.toString(num4)); // [1.5, 3.14, 15.0]

// char 배열은 for 문이나 다른 메소드를 안 써도 된다.
char ch[] = {'h', 'e', 'l', 'l', 'o'};
System.out.println(ch); // hello
}
}

배열을 복사하는 방법

더 읽어보기 »

엔디안은 시스템 프로그래밍에서 많이 쓰이는 용어이다.
엔디안은 메모리의 저장 및 처리 방식을 말하는 것이다.
이는 바이트 순서(Byte Order)와도 큰 관련이 있다.

  1. 빅 엔디안(Big Endian)
    메모리의 높은 번지 부터 저장하는 방식
    MSB(Most Significant Byte), 최상위 바이트부터 차례로 저장한다.
  2. 리틀 엔디안(Little Endian)
    메모리의 낮은 번지 부터 저장 하는 방식
    LSB(Least Significant Byte), 최하위 바이트부터 차례로 저장한다.

4바이트에 값이 저장되는 방식을 알아보자.

10진수 빅 엔디안 리틀 엔디안
0 0x00000000 0x00000000
1 0x00000001 0x01000000
2 0x00000002 0x02000000
3 0x00000003 0x03000000
4 0x00000004 0x04000000
5 0x00000005 0x05000000
6 0x00000006 0x06000000
7 0x00000007 0x07000000
8 0x00000008 0x08000000
9 0x00000009 0x09000000
10 0x0000000A 0x0A000000
11 0x0000000B 0x0B000000
12 0x0000000C 0x0C000000
13 0x0000000D 0x0D000000
14 0x0000000E 0x0E000000
15 0x0000000F 0x0F000000
더 읽어보기 »

공유기에 암호를 걸어놓는다는 것의 의미

무선 공유기의 보안 때문에 AP에 암호를 걸어놓는 경우가 많다.
여기서 무선 공유기에 암호를 건다는 것은…

  1. 무선 공유기에 타인이 접속하는 걸 방지하고자 암호를 건다.
    (WPA2PSK와 같은 방식으로…)
  2. 송수신하는 데이터(평문으로 된 개인정보 등등)을 암호화 하고자 데이터를 암호화 한다.
    (AES와 같은 알고리즘으로…)
더 읽어보기 »

이제는 100메가 광랜을 넘어서 기가의 시대가 열렸다.
100메가 광랜을 쓸 적에 100 메가의 속도를 느껴본 적이 있는가?
이론상 저항 등등에 의해 불가능하지만 그에 준하는 속도라도 느껴본 적 있는가?
그럼 현재 기가에 조금 못 미치더라도 그에 준하는 속도를 느끼고 있는가?
오늘은 그 진실과 상술과 마주해보자.
결론부터 쉽게 풀어서 말하자면
100메가 광랜의 이론상 최대 속도(나올 수가 없음)은 11.9메가이고,
1기가 광랜의 이론상 최대 속도(이 또한 나올 수가 없음)은 119메가이다.

b와 B

사람들이 컴퓨터의 용량을 표기할 때 대소문자를 크게 여기지 않는다.
물론 킬로를 뜻하는 k를 K로 적어도 kilo의 의미가 그대로 담겨있다.
하지만 바이트를 뜻하는 B를 b로 적으면 bit의 뜻이 된다.
일반인들은 잘 모르지만 그게 표준인지는 모르지만 표준과 같이 쓰이고 있다.
인터넷 업체들은 b(it)라고 적으면서 사람들은 B(yte)로 받아들이는 것이다.
8bit = 1Byte, 8배의 속도 차이가 나게 되는 것이다.
1Gb/s = 1Gbps = 10³Mbps = 1000Mbps = 1000/8(MBps) = 125MBps = 125MB/s
즉 1Gb/s는 125MB/s로 환산되어 우리가 피부로 느끼는 속도가 된다.

iB와 B

더 읽어보기 »

이제 사람들이 IT에 많은 관심이 생겨서
1TB 짜리 저장장치를 사도 온전히 1TiB가 아님을 알 수 있다.
내가 여기서 TB와 TiB를 사용했는데, 이에 대해 알아보자.

SI 단위

프랑스어로 Système international d’unités
현 과학계에서 사용하는 표준단위.
표준화의 대표적인 성공사례이자 현재의 국제 과학계가 있을 수 있게 해 준 일등공신.
컴퓨터 용량과 관련된 단위들만 살펴보자.

단위 이름 배수(10진법) 배수(2진법)
Y yotta 1024 ≒280
Z zetta 1021 ≒270
E exa 1018 ≒260
P peta 1015 ≒250
T tera 1012 ≒240
G giga 109 ≒230
M mega 106 ≒220
k kilo 103 ≒210
더 읽어보기 »

윤성우 님의 열혈 C 프로그래밍 동영상 강좌를 열심히 보고 있다.
자바는 메모리 관리를 안 해도 된다지만 공부하면 할 수록 메모리에 자꾸만 관심이 갔다.
그러한 갈증에 대한 해소를 C언어에서 할 수 있었다.

포인터

메모리 주소의 값을 가지고 있는 변수이다.
주된 용도는 특정 변수의 메모리 주소의 값을 가지고 있는 변수이지만,
아래와 같은 것도 가능하다.

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

int main() {
// 0x00000013이 어떤 영역인지 모른다.
// 만약 OS영역이라면 치명적인 오류가 나고, 시스템이 뻗을 수도 있다.
// 하지만 요즘 OS들은 다들 방어적으로들 행동한다고 한다.
// 혹시 모르니 아래 코드는 권장하지 않는다.
long* ptr = 0x00000013; // 에러를 뿜는 컴파일러도 있으니 권장하지 않음.
*ptr = 13;

return 0;
}
더 읽어보기 »

들어가기에 앞서

집중력을 위해 짧은 글을 지향하여 Promise 문법을 설명하지는 않았다.
간단히 jQuery를 사용해본 사람이라면 쉽게 이해할 수 있을 것이다.
내가 찾아본 대부분의 Promise 관련 예제가 setTimeout 위주여서
ajax 위주의 예제를 한 번 정리해보았다.

비동기 코드를 동기식으로 작성하면?

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
const jsonURL = [
"https://perfectacle.github.io/mock/test.json",
"https://perfectacle.github.io/mock/test2.json"
];

const getDataAjax = url => {
const xhr = new XMLHttpRequest();
xhr.open("get", url, true);
xhr.responseType = "json";
xhr.onreadystatechange = () => {
if(xhr.readyState === 4) { // 4 means request is done.
if(xhr.status === 200) { // 200 means status is successful
for(let key in xhr.response) { // 받아온 json 데이터의 키와 값의 쌍을 모두 출력.
if(xhr.response.hasOwnProperty(key))
console.log(`${key}: ${xhr.response[key]}`);
}
} else { // 통신 상에 오류가 있었다면 오류 코드를 출력.
console.error(`http status code: ${xhr.status}`);
}
}
};
xhr.send();
};

// 콘솔창을 키고 새로고침을 10번 정도 해보자.
// 콘솔창에 계속해서 동일한 결과가 출력되는가??
// 비동기 작업이기 때문에 순서를 보장하기 힘들다.
// 원래는 아래와 같이 나와야한다.
// test: hi
// test2: hi
// test: hi
// test: hi
// test2: hi
// test2: hi
// test: hi
// test2: hi
// test: hi
// test2: hi
getDataAjax(jsonURL[0]);
getDataAjax(jsonURL[1]);
getDataAjax(jsonURL[0]);
getDataAjax(jsonURL[0]);
getDataAjax(jsonURL[1]);
getDataAjax(jsonURL[1]);
getDataAjax(jsonURL[0]);
getDataAjax(jsonURL[1]);
getDataAjax(jsonURL[0]);
getDataAjax(jsonURL[1]);
더 읽어보기 »

반복문

for문

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
public class test2 {
public static void main(String[] args) {
System.out.println("i \t i % 3 \t i / 3");
for(int i=0; i<12;)
System.out.printf("%d \t %d \t %d%n", i, i%3, i++/3);
/*
i % n에서 % 연산자는 n개의 숫자가 연속적으로 순환하면서 나오고
i / n에서 / 연산자는 동일한 숫자가 n번 연속해서 나온다.
알고리즘 어딘가 쓰일지 모르니 기억해두자.
i i % 3 i / 3
0 0 0
1 1 0
2 2 0
3 0 1
4 1 1
5 2 1
6 0 2
7 1 2
8 2 2
9 0 3
10 1 3
11 2 3
*/
}
}

향상된 for문

더 읽어보기 »
0%