변수 선언
type 변수명(다수 가능);
int i, j, k;
char c, ch;
float f, salary;
double d;
당연히 같은 스코프 내에서 같은 이름으로 재선언은 불가능하다.
변수 초기화
/* 다른 파일에서 정의된 전역 변수,함수를 현재 파일에서 사용할 때 extern키워드 사용*/
extern int d = 5, f = 5;
int a = 3;
byte z = 22;
char x = 'c';
변수 초기화를 해주지 않으면 쓰레기값이 들어있기 때문에 꼭 초기화를 해주고 사용하자!
// 컴파일러에게 외부 변수의 존재를 알림(현재 파일에 정의되지 않았으니 외부에서 참조하겠다)
// C-스타일의 전방 선언 (declaration)
extern int externalInt;
int main (void) {
//변수 선언 & 정의 definition (메모리 주소가 정해짐)
int a, b;
int c;
float f;
//변수 초기화(initialization)
a = 10;
b = 20;
c = a + b;
NSLog(@"value of c : %d \n", c);
f = 70.0/3.0;
NSLog(@"value of f : %f \n", f);
return 0;
}
선언 vs 정의
선언은 컴파일러에게 타입과 이름만 알려주는 것이고,
정의는 메모리 할당까지 이루어 지는 경우를 의미한다.
대부분의 변수는 선언과 정의가 함께 이루어진다.
int a; 라고 하면 아 int 자료형의 a라는 식별자를 사용하고(선언) 4byte의 메모리 공간이 필요하구나!(정의)
하지만 아래의 경우는 주소 바인딩이 되지 않는다.
컴파일러는 아 이런 함수와 구조체가 있구나?를 알고 컴파일을 하고 (주소 바인딩이 없으니 선언임)
이후 링크 단계에서 해당 함수의 정의부와 구조체의 정의부를 통해 적절한 메모리 주소가 바인딩 되게 된다.
// 함수 선언
void someFunction(void);
// 구조체 선언
struct x;
C언어 처리 단계를 간단히 살펴보자면 아래와 같다.
전처리
- 전처리기에 의해 #import, #define등의 내용을 현재 소스에 포함시킨다. (컴파일러에게 전달하기 위해)
컴파일
- 컴파일러에 의해 전처리된 소스를 기계어로 변환한다.(인라인 함수는 이때 바인딩)
링크
- 링커에 의해 컴파일된 소스코드와 라이브러리 코드를 결합해 실행 가능한 바이너리 파일을 만든다.
- 주로 함수 메모리 바인딩이 링크 단계에서 이루어진다.
처음에 c에서는 왜 이런식으로 하지?라는 의문이 있었는데 코드의 양이 많아지다 보니까,
전방에 변수와 함수들이 쫙 선언되어 있으면 전체적인 흐름을 파악하기에 유용하더라..
함수의 선언과 정의 예시
//함수 선언
int myFunc();
int main() {
//함수 호출
int i = myFunc();
}
//함수 정의
int myFunc() {
return 777;
}
Lvalue와 Rvalue
objective c에서는 두 가지 종류의 표현식이 있다.
lvalue(left value)
위치를 나타내는 표현식. 할당 연산자(=)의 왼쪽에 오는 표현식을 말한다.
변수, 배열 요소, 구조체 멤버 등이 lvalue이다.
rvalue(right value)
'값'을 말한다. 값을 생성하거나 계산하는 표현식을 의미한다.
상수, 리터럴, 함수 리턴값 등이 rvalue이다.
//lvalue //숫자 리터럴 rvalue
int lvalue = 10;
//rvalue = rvalue라서 틀린 표현
//10 = 20;
c 프로젝트 하면서 lvalue 뭐시기 에러가 꽤 났었는데 별거 아니었네.. 그냥 이런거였다 ㅋㅋ
상수
말 그대로 변수와 달리 고정된 값. 리터럴이라고도 하며 숫자 리터럴, 문자열 리터럴 등으로 자주 언급된다.
상수 정의
#define 전처리문 사용
#import <Foundation/Foundation.h>
#define LENGTH 10
#define WIDTH 5
#define NEWLINE '\n'
int main() {
int area;
area = LENGTH * WIDTH;
NSLog(@"AREA : %d", area);
NSLog(@"%c", NEWLINE);
return 0;
}
상수는 주로 전부 대문자를 사용한다. 또한 할당 연산자나 세미콜론도 사용하지 않는다. 그냥 띄어쓰기로 구분한다.
#define은 전처리기에 의해 전처리 단계에서 처리되며 단순한 치환이 이루어져서(그냥 해당 값으로 바뀜)
컴파일러에 의해 타입 검사가 일어나지 않는다.
또한 파일 전체에서 사용할 수 있다.
const 키워드
#import <Foundation/Foundation.h>
int main() {
const int LENGTH = 10;
const int WIDTH = 5;
const char NEWLINE = '\n';
int area;
area = LENGTH * WIDTH;
NSLog(@"AREA : %d", area);
NSLog(@"%c", NEWLINE);
return 0;
}
똑같은 변수 정의이기에 타입을 지정해줘야 한다. (컴파일러 타입 검사 받음)
또한 블록 스코프에 따라 사용 범위가 달라진다.
const가 타입검사도 받을 수 있기에 안전하지만, 주로 파일 전체에서 계속 사용하는 값은
define으로 정의하고 내부에서 사용하는 경우에는 const를 사용하면 되겠다.
어떤 것이 더 권장된다기 보다는 상황에 따라 다름!
'iOS Developer > Objective-C' 카테고리의 다른 글
7. Objective-C 함수(call by value, call by reference) (0) | 2024.05.06 |
---|---|
6. Objective-C 반복문/조건문 (0) | 2024.05.06 |
3. Objective-C 자료형 (0) | 2024.05.05 |
2. Objective-C / 기본 구문 및 구조 (0) | 2024.05.05 |
1. Objective-C / Hello world! (0) | 2024.05.03 |