[C/C++] FILE 에 대하여 질문이 있어요.

ck7683의 이미지

FILE *fp;
fopen_s(&fp, "input.txt", "r");

보통 간단하고 쉽게 볼 수 있는 파일 오픈인데

생각해보니까 문득 궁금한게 생겼어요.

보통
변수에 포인터를 달면
int* pt;

그걸 사용하기 위해서 int로 선언된 값의 위치라던가 새로 생성하잖아요?
int a;
int *pt= &a;
-
int *pt = new int;

그런데 FILE은 왜 FILE* 로 생성하라고 배우는 거고
왜 대부분 파일과 관련된 함수들은 FILE 를 인수로 받기보단 FILE*를 인수로 받나요?
fscanf, fgets, fputs, fprintf

파일 오픈 하는 함수(fopen_s)는 왜 FILE** 로 인수를 받나요?

bbaijang의 이미지

1. FILE의 사이즈 만큼을 return 할 수 없습니다. FILE *를 return 하면 32비트 머신에서 4바이트만 복사하면 됩니다.
그 이상 사이즈를 C/C++에서 return 할 방법이 없죠. (call by value와 call by reference 찾아보세요 ^^)
2. FILE의 fp를 fopen_s함수에서는 첫번째 인수로 넘겨줍니다.
fopen_s 내부를 추측하면, 넘겨준 첫번째 인수에 함수 내부에서 얻어온 fp를 첫번째 인수에 넘겨줘서 본인 스택을 벗어나게 하겠죠?
2번을 더 잘 이해하고 싶으시면 return으로 값을 돌려주는 함수를 한 번 작성해보세요.

문제는 +1을 해서 출력합니다.
ex) 10일 경우 +1을 해줍니다. 그 후에 값을 출력하면 됩니다.
int number = 10;
sum_one(&number); // sum_one 함수는 return이 void여야만 하고, 입력으로 받은 number 값에 +1을 해줍니다.
printf("%d", number);

이것이 원할히 동작하도록 sum_one함수를 만들어보면 됩니다.

ck7683의 이미지

2번은 1번에 질문과 연관되어 있어요.
FILE 로 만들어서 FILE* 로 넘겨주면 안되나는 뜻이었어요.

그런데 1번은 제가 이해 안되는게...

__int64 Test(){
return 200010001000;
}
__int64 Test3(__int64 n){
return n;
}
int main(void){

__int64 k = Test();
k = Test3(k);

위에 코드처럼 쓰면
return으로 64비트를 사용했고
인수로도 64비트를 사용했는데.
정상적으로 k값이 200010001000 으로 읽히네요.

음 그리고

struct ABCD{
int a, b, c, d, e, f,g,h,i,j,k;
};
typedef struct ABCD ABCD;
ABCD Test(ABCD a) { return a; }
int main()
{
ABCD a, b;
a.a = 1, a.b = 2, a.c = 3, a.d = 4, a.e = 5, a.f = 6, a.k = 10;
printf("%d", sizeof(a));
b = Test(a);

printf("%d", sizeof(FILE));
//int a[10] = { 0 };
//InputData(a);

return 0;
}

FILE 쫓아가보니 어떤 구조체 이길래
4바이트를 넘어 FILE의 사이즈보다도 큰걸 썼을 때, 어떤 문제가 발생하나 확인하려고 했는데
b.k 가 10으로 제대로 나오드라구요.
그럼 FILE 사이즈 그대로 리턴해도 문제가 안 생길것 같아서
1번의 답변이 이해가 어려워요

익명 사용자의 이미지

> 1. FILE의 사이즈 만큼을 return 할 수 없습니다. FILE *를 return 하면 32비트 머신에서 4바이트만 복사하면 됩니다.
> 그 이상 사이즈를 C/C++에서 return 할 방법이 없죠. (call by value와 call by reference 찾아보세요 ^^)

완전히 잘못된 이야기입니다.
C/C++의 함수는 어떤 크기의 데이터도 반환할 수 있습니다.

bbaijang의 이미지

윗분 말씀대로 어떤 크기의 데이터도 반환할 수 있습니다.

bbaijang의 이미지

return 시에 동작은 다음과 같습니다.
불려진 함수에 원함수로 값을 전달해 줘야 하는데요.
특정한 공간에 값을 넣게 됩니다.
이 특정한 공간의 크기는 32비트 머신에서 4바이트정도 됩니다.
그 이상의 크기인 경우에는 다른 메모리에 데이터를 저장해서... return으로 그 메모리의 주소값을 전달합니다.

*는 32비트 머신에서 4바이트 정도이기때문에 포인터로 전달하면 특정한 공간만 사용하면 되지만,
그 이상의 크기인 경우에는 한번더 작업을 수행하게 됩니다. (머신별로 다를 수도 있습니다.)

추가로 struct를 바로 assign을 할 경우에 대한 작업도 원함수에서 해줘야 하는데요.
struct에서 오퍼레이터를 구현해보진 않았지만... 아마 가능하지 않을까 합니다.
그 작업을 추가로 수행햐아 하니

성능상의 이슈로 포인터를 전달하게 됩니다.

kukyakya의 이미지

성능상의 이슈보다는 추상화 개념으로 보시면 됩니다.

사용자 입장에서는 해당 포인터가 FILE* 것만 알고 있으면 제공되는 파일입출력 함수를 쓸 수 있고, FILE 구조체의 내부에 대해 알 필요가 없습니다.

ck7683의 이미지

성능과 추상화 토끼 두 마리 다 잡는다고 보면 되겠군요

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.