[C 입문중] 포인터 상수, 포인터 변수의 차이좀 헤깔리네요.

meekdmn의 이미지

#include <stdio.h>
#define NUM 5

typedef struct _student Student;
struct _student
{
    int kor;
};

void pointer_test(Student *s);
void pointer_test1(Student s1[NUM]);


int main()
{
	Student student[NUM];
	int i;
	for(i=0;i<NUM;i++){
		student[i].kor = i;
	}
	printf("student address --> %x\n",student);
		
	for(i=0;i<NUM;i++){
		printf("%d\n",*student);
		printf("%x\n",student);

/*여기는 student가 포인터 상수죠? 그래서 	상수값을 바꾸려고 하면 안되죠.?*/
		student++;
	}
	
	pointer_test(student);
	pointer_test1(student);
}

void pointer_test(Student *s)
{
	int i;
	for(i=0;i<NUM;i++){
		printf("%d\n",*s);
		printf("%x\n",s);
		s++;
	}
	
}

/*근데 여기서 s1은 포인터 상수가 아닌가요.?
제가 간단하게 아는 바로는 배열명은 주소값을 가지게 되고 이는 바뀔 수 없으므로 포인터 상수라 한다. 였는데..아래에서 s1++;을 해줄 수 있단거에 대해서 의문이..생겼습니다.*/
void pointer_test1(Student s1[NUM])
{
	int i;
	for(i=0;i<NUM;i++){
		printf("%d\n",*s1);
		printf("%x\n",s1);
		s1++;
	}
}

배열명은 포인터 상수이고 , 함수로 전달된 배열명은 그 함수에서 새로이 생성이 되어서? 포인터 상수가 아닌건가.? 주소를 찍어보면 같은거 보니깐 새로이 생성은 아니고 참조인것 같은데.

pointer_test1(Student s1[NUM])의 s1과 main에서 student와는 어떤 관계가 있는거죠.?

void pointer_test1(Student s1[NUM]) 와
void pointer_test1(Student *s)
의 궁극적인 차이는 없는건가요.?

입문중인데 한번 헤깔리니깐..이랬다고 믿던 것 마저 흔들려서. 저의 답답함을 좀 식혀 주세여..

감사합니다 꾸뻑.

doldori의 이미지

meekdmn wrote:
/*여기는 student가 포인터 상수죠? 그래서 	상수값을 바꾸려고 하면 안되죠.?*/
		student++;
	}

student++이 안되는 이유는 포인터 상수(pointer constant)라서 그런 것이 아니라
변경 가능한 좌변값(modifiable l-value)이 아니기 때문입니다. 이것은 포인터
상수와는 전혀 다른 것입니다. 포인터 상수의 예로는 NULL이 있습니다.

meekdmn wrote:
void pointer_test(Student *s)
{
	int i;
	for(i=0;i<NUM;i++){
		printf("%d\n",*s);
		printf("%x\n",s);
		s++;
	}
}

/*근데 여기서 s1은 포인터 상수가 아닌가요.?
제가 간단하게 아는 바로는 배열명은 주소값을 가지게 되고 이는 바뀔 수 없으므로 포인터 상수라 한다. 였는데..아래에서 s1++;을 해줄 수 있단거에 대해서 의문이..생겼습니다.*/

main()의 배열명 student는 함수로 전달되면서 포인터로 변환됩니다. 이 동작을 코드로 나타내면
    Student* p = student;
    pointer_test(p);

정도가 될 수 있습니다.

meekdmn wrote:

배열명은 포인터 상수이고 , 함수로 전달된 배열명은 그 함수에서 새로이 생성이 되어서? 포인터 상수가 아닌건가.? 주소를 찍어보면 같은거 보니깐 새로이 생성은 아니고 참조인것 같은데.

배열과 포인터는 전혀 다른 것이지만 많은 경우에 배열명은 포인터로 변환될 수
있습니다. 함수로 전달된 배열명은 배열의 선두 주소를 가리키는 포인터로 바뀌고
함수 내부에서는 변환된 포인터에 대한 복사본이 사용되는 것입니다. 당연히
같은 주소를 가리키게 됩니다.

meekdmn wrote:

pointer_test1(Student s1[NUM])의 s1과 main에서 student와는 어떤 관계가 있는거죠.?

void pointer_test1(Student s1[NUM]) 와
void pointer_test1(Student *s)
의 궁극적인 차이는 없는건가요.?


예, 똑같은 함수입니다. pointer_test1() 안에서는 전달된 것이 배열인지 포인터인지
구별할 수 없습니다.
익명 사용자의 이미지

s1++;을 해줄 수 있단거에 대해서 의문이..생겼습니다

함수 호출이 call by value 아닌가요..?

lsj0713의 이미지

Anonymous wrote:
s1++;을 해줄 수 있단거에 대해서 의문이..생겼습니다

함수 호출이 call by value 아닌가요..?

함수 호출의 형식과는 전혀 관련이 없고, C가 함수의 매개변수에 적용하는 특별한 변환 규칙과 관련이 있습니다.

#include <stdio.h>

void func(int a[])
{
    printf("%d\n", *a);
    ++a;
    printf("%d\n", *a);
}

int main(void)
{
    int arr[3] = {1, 2, 3};
    func(arr);
    return 0;
}

위의 프로그램이 전혀 틀린 곳이 없는 프로그램이 될 수 있는 것은, 함수 정의나 선언의 파라미터 리스트에 사용된 모든 형태의 array of ... 꼴의 변수는 자동으로 pointer to ... 형태로 변환되기 때문입니다. 따라서 실제로 a의 데이터형은 array of int[]가 아니라 pointer to int입니다.

Quote:

C99 6.7.5.3 Function declarators 중에서...

7. "array of type"으로 정의된 파라미터는 "qualified pointer to type"으로 조정된다. [ ] 안에 있던 형 한정자(type qualifier)는 그대로 붙여 사용한다.

e.g) "int [const][5]" -> "int (* const)[5]"

(역자 주: 제가 어설프게 한 번역이라 의역과 편집이 섞여있으며 오역의 위험이 크니, 조심하시길 바랍니다. ^^;)

위와 같은 규칙 덕분에 함수 선언부에는 배열 형태로 적고 함수 정의부에는 포인터 형태로, 혹은 그 반대로 적어놓아도 아무런 문제가 없습니다.

void func(int a[]);    // 함수 선언에는 배열 형태를 사용

void func(int *a) { ... }    // 함수 정의에는 포인터 형태를 사용

참고로, 다차원 배열의 경우에는 다음과 같이 가장 바깥쪽의 배열만 벗겨져 포인터 형태로 변환됩니다.

int func(int a[], short b[3][4], long c[][6][7]) { ... }
-> int func(int *a, short (*b)[4], long (*c)[6][7]) { ... }

위와 같은 규칙 때문에 함수가 호출될 때 배열은 call by reference로 전달된다고 말하기도 하는데, 틀린 설명입니다. C언어의 함수는 배열을 매개변수로 전달할 수 없습니다. 다만 포인터를 이용하여 배열의 주소값만을 전달할 수 있을 뿐입니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.