포인터 이해(2)

rgbi3307의 이미지

#include /stdio.h/

int main (void)
{
char *a;
int *b;
float *c;
double *d;

printf ("a=%d, b=%d, c=%d, d=%d\n", sizeof(a), sizeof(b), sizeof(c), sizeof(d));

return 0;
}

printf() 함수의 출력은 어떻게 될까요?

From:
*알지비 (메신저: rgbi3307(at)nate.com)
*학창시절 마이크로마우스를 만들었고, 10년동안 IT관련 개발자로 일하고 있음.
*틈틈히 커널연구회(http://www.kernel.kr/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

hongwoo의 이미지

#include <stdio.h>
 
int main (void)
{
    char *a;
    int *b;
    float *c;
    double *d;
 
    printf ("a=%d, b=%d, c=%d, d=%d\n", sizeof(a), sizeof(b), sizeof(c), sizeof(d));
 
    return 0;
}

앞뒤로 code tag 붙여주시면 더 좋을듯 ^^ ~

-----------------------------
in the real-time scheduler !

-----------------------------
in the real-time scheduler !

Fe.head의 이미지

32비트 운영체제에서는 모두 4
64비트 운영체제에서는 모두 8 이 아닐까요?
-----------------------
과거를 알고 싶거든 오늘의 네 모습을 보아라. 그것이 과거의 너니라.
그리고 내일을 알고 싶으냐? 그러면 오늘의 너를 보아라. 그것이 바로 미래의 너니라.
-----------------------
내가 쓰는 글은 틀릴 수 있습니다.

고작 블로킹 하나, 고작 25점 중에 1점, 고작 부활동
"만약 그 순간이 온다면 그때가 네가 배구에 빠지는 순간이야"

semmal의 이미지

C언어의 주소크기는 하드웨어>운영체제>컴파일러 순으로 종속적일겁니다. 아마도
------------------------------
How many legs does a dog have?

------------------------------
How many legs does a dog have?

lifthrasiir의 이미지

네 개 모두 다르게 나오는 환경도 있을 수 있습니다. 다만 void*는 아무래도 다른 모든 포인터들의 크기보다 크거나 같은게 일반...적이겠죠. (void*와 other_type* 간의 무손실 변환은 보장되니까. 물론 other_type*에 쓸데 없는 패딩이 들어 있거나 한다면 다를 수도 있습니다.)

seungrye의 이미지

다르게 나올수가 있...나요?
어차피 포인터라는게 주소를 가르키는건데,
모든 주소를 가리킬수 있을정도의 크기(32bit 컴퓨터의 경우 4byte)로 통일되어 있을거 같은데요.
(제가 그렇게 배워서...;;)

제가 잘못알고 있다면 가르침 부탁드립니다.(__)

rgbi3307의 이미지

포인터는 주소이므로...

4개가 다르게 나오는 경우는 없습니다.

4개가 동일하게 모두 다른 크기로 나올 수는 있겠죠.

16비트 아키텍쳐에서는 2, 2, 2, 2
32비트 아키텍쳐에서는 4, 4, 4, 4
....

(void*) 는 데이터 형변환을 아무거나 해줄 수 있다는 것이죠.

From:
*알지비 (메신저: rgbi3307(at)nate.com)
*학창시절 마이크로마우스를 만들었고, 10년동안 IT관련 개발자로 일하고 있음.
*틈틈히 커널연구회(http://www.kernel.kr/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

From:
*알지비 (메일: rgbi3307(at)nate.com)
*커널연구회(http://www.kernel.bz/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

cppig1995의 이미지

void *와 char *의 크기가 같다는 것 외에 포인터의 크기에 대한 보장은 C 표준에 없는 걸로 알고 있습니다.
(네, 역시 메인프레임은 넘사벽이지요.)

Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.

lifthrasiir의 이미지

포인터가 주소가 아닐 수 있습니다. 단지 현재 컴퓨터에서 포인터를 주소로 취급하는 것이 가장 자연스럽기 때문에 그렇게 하는 것 뿐입니다. (자세한 내용은 KLDP에서 몇 번 논의된 적이 있으므로 생략합니다. C FAQS에도 유사한 내용이 있습니다.)

rgbi3307의 이미지

포인터(주소)의 크기는
8비트 아키텍쳐에서는 1바이트
16비트 아키텍쳐에서는 2바이트
32비트 아키텍쳐에서는 4바이트
64비트 아키텍쳐에서는 8바이트
128비트 아키텍쳐에서는 16바이트
.... 입니다. (물론 다르게 설계할 수 있는데, 그동안 이렇게 설계한듯..)

8비트로 표현가능한 경우의 수는 2의8승(256),
즉, 1바이트 크기의 주소로 최대 256바이트 메모리 접근가능.

16비트로 표현가능한 경우의 수는 2의16승(64K),
즉, 2바이트 크기의 주소로 최대 64K바이트 메모리 접근가능.

32비트로 표현가능한 경우의 수는 2의32승(4G),
즉, 4바이트 크기의 주소로 최대 4G바이트 메모리 접근가능.

64비트로 표현가능한 경우의 수는 2의64승(16x1Gx1G == 16 x 10의18승),
즉, 8바이트 크기의 주소로 최대 16 x 10의18승 바이트 메모리 접근가능.

.....

현재 컴퓨터 논리회로가 On/Off 스위치(TTL:Transistor-Transistor Logic)방식이므로,
2진법으로 표현되는듯...

From:
*알지비 (메신저: rgbi3307(at)nate.com)
*학창시절 마이크로마우스를 만들었고, 10년동안 IT관련 개발자로 일하고 있음.
*틈틈히 커널연구회(http://www.kernel.kr/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

From:
*알지비 (메일: rgbi3307(at)nate.com)
*커널연구회(http://www.kernel.bz/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

lifthrasiir의 이미지

정말로 잘못 알고 계신 것입니다. 포인터가 주소와 완벽하게 같지 않다는 사실을 차치하고더라도, "주소"라는 것 자체가 아키텍처마다 다르게 정의될 수 있습니다. (물론 대부분의 경우 포인터와 주소가 같게 취급된다고 기억하는 것 자체는 상관 없지만 "아닌 경우도 있다"라는 걸 기억하는 건 중요합니다. 정말로 그런 기계 만나면 답이 없으니까요.)

혹시 옛날에 16비트 프로그램을 짜 보셨다면 거기서 실제로 참조 가능한 주소가 16비트가 아니라 20비트(세그먼트 때문에)라는 걸 기억하실 지 모르겠군요. 어떤 메인프레임 아키텍처에서는 워드 단위(32비트였나?)로만 메모리를 접근할 수 있기 때문에 워드에 대한 포인터와 바이트에 대한 포인터(워드에 대한 포인터 + 워드 안에서의 바이트 오프셋 몇 비트)가 완전히 다르게 취급되는 경우도 있다고 들었습니다.

cppig1995의 이미지

286에는 near와 far 포인터가 있었고
포인터 크기는 16, 32비트 두 종류였는데
메모리 영역은 20비트였다죠?

이건 무슨 조화일까요?

Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.

rgbi3307의 이미지

논리적 주소: CPU안의 레지스터와 가산기 사이의 연산(8비트, 16비트, 32비트...)
물리적 주소: 실제 메모리 반도체에 입력되는 20가닥의 전류 흐름선(2의20승은 1M바이트 크기)

논리적인 연산은 CPU안의 레지스터 크기에 많은 영향을 받습니다.
보통,
8비트 아키텍쳐에서 CPU안의 레지스터 크기는 8비트
16비트 아키텍쳐는 16비트
32비트 아키텍쳐는 32비트....

어셈블러 및 C언어 컴파일러들은 CPU 아키텍쳐안의 레지스터 크기에 따라서 연산이 됩니다.
제가 주소의 크기가 결정된다고 언급하는 것은, CPU 레지스터의 크기입니다.(프로그래밍 코딩 수준에서 접근)

저는 포인터==주소(포인터를 주소로 한글표현)로 이야기한 것이기 때문에,
"포인터가 주소가 아닐 수 있습니다" 라고 언급하신 부분에 대해서는,
보충 설명 부탁합니다.

From:
*알지비 (메신저: rgbi3307(at)nate.com)
*학창시절 마이크로마우스를 만들었고, 10년동안 IT관련 개발자로 일하고 있음.
*틈틈히 커널연구회(http://www.kernel.kr/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

From:
*알지비 (메일: rgbi3307(at)nate.com)
*커널연구회(http://www.kernel.bz/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

죠커의 이미지

우리집을 찾을 때 우체국이 만든 주소를 쓸 수도 있지만 GPS 주소를 쓸 수 도 있습니다. C언어는 구현(implementation)이 어떤 선택을 하는지 상관하지 않습니다. 덧붙여 C언어는 가능한한 하드웨어 독립적으로 스펙을 기술하고 있습니다. H&S, 표준스펙, 전웅씨의 책등을 참고하십시요.

- 죠커's blog / HanIRC:#CN

rgbi3307의 이미지

우리집주소:
우체국주소:
GPS주소:
누가 어떻게 사용한다는 것인가요?

From:
*알지비 (메신저: rgbi3307(at)nate.com)
*학창시절 마이크로마우스를 만들었고, 10년동안 IT관련 개발자로 일하고 있음.
*틈틈히 커널연구회(http://www.kernel.kr/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

From:
*알지비 (메일: rgbi3307(at)nate.com)
*커널연구회(http://www.kernel.bz/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

jachin의 이미지

우리집주소는 일반적으로 우리집 주소를 알고 있는 사람들이 쓰고 있고,
우체국주소는 우체국 직원들이 각 집의 방문순서를 용이하게 만들기 위해 쓰면서,
동시에 정부에서 지정하고 있는 '도로명'기준 주소로도 병기해서 사용하고 있습니다.
GPS주소는 택배회사 직원들이 주로 사용하고 있는 것이지요.
====
( - -)a 이제는 학생으로 가장한 백수가 아닌 진짜 백수가 되어야겠다.

lifthrasiir의 이미지

논리적인 것과 물리적인 것이 구분되는 이유는 논리적인 것이 생각하기 쉬울 뿐만 아니라 물리적인 건 언제나 바뀔 여지가 있기 때문입니다. C 프로그래밍 언어가 얼마나 많이 사용되는지 알고 계신가요? 제가 기억하는 대로 몇 가지 사례를 나열해 보겠습니다.

- 일반적인 프로세서(x86, x86-64, ARM, MIPS 따위)로 컴파일할 때.
- 일반적인 프로세서에서 실시간으로 해석해서 인터프리트할 때. ChCINT 같은 것을 쓰면 파이썬이나 루비(irb) 같은 대화식 인터프리트 환경을 C 언어로 사용할 수 있습니다. C가 컴파일되는 언어라굽쇼?
- 일반적이지 않은 기계어로 컴파일할 때. 이를테면 엔비디아 CUDA는 C 언어의 부분집합을 GPU 기계어로 컴파일해 줍니다. GPU는 그 자체로 매우 병렬적이기 때문에 프로그래밍 모델도 완전히 다르며 (HLSL/GLSL/Cg 등의 셰이딩 언어를 써 보셨다면 이해하시겠지만) 일반적인 언어를 실행하는 데도 제약이 꽤 있는데, 먼 옛날의 GPU는 분기 명령조차 지원하지 않아 곱셈으로 분기를 구현해야 했습니다. 그래서 GPU 용으로 컴파일하려면 모든 함수들을 하나로 뭉쳐서 합쳐 컴파일해야 하고, 이때문에 CUDA는 함수 포인터나 재귀 호출을 지원하지 않습니다. 하지만 그래도 C 표준은 잘 구현하더군요.
- C를 다른 언어로 컴파일하는 경우도 왕왕 있습니다. 실용적인 예를 들면, C 라이브러리는 필요한데 그걸 실행할 환경에서는 아무 기계어나 실행 불가능하고 자바나 루아같은 언어로만 코딩할 수 있는 경우가 있습니다. Clue 같은 프로젝트가 바로 이런 경우를 위해 존재하고, 가끔씩은 c2bf(C를 Brainfuck으로 컴파일) 같은 미친 프로젝트도 있습니다.

이제 C가 기계와 전혀 상관이 없는, 또는 적어도 그렇게 설계된 언어라는 걸 이해하시겠습니까? 님께서 아시는 C 프로그래밍 언어는 빙산의 일각에 불과합니다.

rgbi3307의 이미지

"포인터가 주소가 아닐 수 있습니다" 라는 것에 대한 보충설명이 없군요.

From:
*알지비 (메신저: rgbi3307(at)nate.com)
*학창시절 마이크로마우스를 만들었고, 10년동안 IT관련 개발자로 일하고 있음.
*틈틈히 커널연구회(http://www.kernel.kr/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

From:
*알지비 (메일: rgbi3307(at)nate.com)
*커널연구회(http://www.kernel.bz/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

select99의 이미지

님이 올린다른글들 주욱보았는데.. 님이 그동안 잘못알고 계셨다고 보이네요..

rgbi3307의 이미지

"어떤 부분을 이렇게 잘못알고 있네요"라는 식으로 지적해 주시면 고맙겠습니다.

From:
*알지비 (메신저: rgbi3307(at)nate.com)
*학창시절 마이크로마우스를 만들었고, 10년동안 IT관련 개발자로 일하고 있음.
*틈틈히 커널연구회(http://www.kernel.kr/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

From:
*알지비 (메일: rgbi3307(at)nate.com)
*커널연구회(http://www.kernel.bz/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

jachin의 이미지

포인터는 메모리 주소를 가리키는 데이터 형식입니다.
메모리 주소는 CPU의 Memory Address Bus Bandwidth(주소 버스 범위)를 기준으로 결정합니다.
DATA Bus Bandwidth(데이터 버스 범위)를 기준으로 삼지 않습니다.

8 bit 가 제일 작은 데이터 버스 폭을 갖고 있으니, 예를 들어 설명해봅니다.
설명하신 대로 8 bit 의 포인터를 갖는 경우,
주 메모리 영역에서 가리킬 수 있는 최대값은 2^8 = 256 Bytes 가 됩니다.
그러나 8 bit 마이크로 컨트롤러와 CPU 모두 256 Bytes 이상의 메모리 영역을 갖을 수 있습니다.
그렇다면 256 Bytes 이상의 메모리 영역을 어떻게 포인터로 가리킬 수 있을까요?
====
( - -)a 이제는 학생으로 가장한 백수가 아닌 진짜 백수가 되어야겠다.

죠커의 이미지

C/C++ 언어가 선형 메모리 모델을 염두하지 않은 것을 감안하면 정확한 설명은 아니라고 생각합니다.

- 죠커's blog / HanIRC:#CN

jachin의 이미지

결국 포인터의 포인터(2차원 배열 포인터)를 이용한 방식의 참조로
Memory Mapped I/O 영역을 참조하면 되겠군요.

CPU 구조 중에 데이터 버스 폭보다 큰 주소 버스 폭을 갖는 메모리 구조의 CPU로 예를 들어야 하겠네요.

실제로 8051 CPU 는
8 bit CPU 이지만 내부 4 Kbytes, 외부 64 KBytes 까지
접근이 가능하도록 설계되어 있습니다.

8051 에서도 C 컴파일러를 사용하며, C 컴파일러의 설정에 따라
포인터 값이 달라진다는 것도 들어서 얘기할 수 있을것 같습니다.

또 뭘로 예를 들 수 있을까요?
====
( - -)a 이제는 학생으로 가장한 백수가 아닌 진짜 백수가 되어야겠다.

죠커의 이미지

옆에 찾기에서 포인터라고 입력하시면 이와 관련된 내용이 잔뜩있습니다. 이 주제는 거의 분기별로 나오는 것 같군요. 검색을 해보세요.

- 죠커's blog / HanIRC:#CN

lifthrasiir의 이미지

Clue는 C를 루아로 컴파일하는데 루아에 주소라는 개념이 있긴 한가요? 그렇다고 Clue에서 지원하는 배열이 C 표준에 부합하지 않을 정도로 단순화된 것도 아닙니다. C 언어는 이런 상황을 허용하도록 포인터 연산에 매우 강한 제약을 부여하고 있는데, 간단한 예를 들자면 서로 다른 두 배열의 원소를 가리키는 두 포인터의 비교는 undefined입니다. (i.e. int a[5], b[6]; 일 때 &a[i]와 &b[j] 사이의 비교가 정의되어 있지 않음)

제가 글을 잘 못 쓴 건지, 님께서 제가 쓴 글을 제대로 읽어 보지 않은 건지, 아니면 루아가 그냥 C만치 저수준 언어라고 생각하시는 건지는 모르겠습니다만, 조금만 찾아 보면 이해할 수 있는 내용에 대해서 구체적인 내용이 없는 질문은 더 이상 답변을 사절하겠습니다.

ifree의 이미지

286 은 16비트 시스템이라 16비트 레지스터 2개를 써서 주소를 나타내었는데,
16비트로 나타낼 수 있는 최대 수인 64K 가 하나의 메모리 세그먼트를 구성하고
이 세그먼트 16개가 모여서 1M 의 메모리를 구성했습니다.
따라서 하위 16비트 상위 4비트 해서 20비트의 메모리 주소를 가지는 셈이지만
기본적으로는 64K 씩 분할되 있는 형식입니다.
하지만 시스템 메모리 빼고 실제로는 500K 도 쓸 수 없었던 기억이 나네요.

phonon의 이미지

C의 메모리나 시스템이 어찌 되었든지간에 하드웨어나 컴파일러의 스펙을 보는 수 밖에 없습니다.
메뉴얼에 나와 있는 내용들에 맞추어야 뭐든지 작동하는 것만 진실아닌가요.