sourcetip

구조 vs.범위의 함수 정의

fileupload 2023. 10. 15. 17:33
반응형

구조 vs.범위의 함수 정의

제가 알기로는 C에서 합법적인 것으로 알고 있습니다.

축구의

struct foo {
   int a;
};

바의

struct foo {
    char a;
};

그러나 기능이 있는 것과 같은 것은 불법입니다.

축구의

int foo() {
    return 1;
}

바의

int foo() {
    return 0;
}

합니다의 ())가 foo).

왜 그런 것일까요?구조명과 함수명은 C가 하나를 처리하지 못하고 다른 하나는 처리하지 못하게 만드는 차이점이 무엇입니까?또한 이 동작이 C++로 확장됩니까?

왜 그런 것일까요?

struct foo {
   int a;
};

개체를 만들기 위한 템플릿을 정의합니다.객체나 함수를 만들지 않습니다.~하지 않는 한struct foo컴파일러/링커에 관한 한 코드 어딘가에 사용됩니다. 이러한 코드 라인은 존재하지 않을 수도 있습니다.

가 되지 않는 C C++ 를 하시기 바랍니다.struct정의들.

에 대한 .struct foo당신이 게시한 코드에서, 당신이 그들의 사용법을 섞지 않는 한, C 프로그램에서는 괜찮습니다.

그러나 C++에서는 합법적이지 않습니다.C++에서는 외부 링크가 있으므로 동일하게 정의해야 합니다.자세한 내용은 3.2 하나의 정의 규칙/5 참조.

이 경우 구별되는 개념을 연결이라고 합니다.

C 구조에서 union 또는 enum 태그에는 연결이 없습니다.그들은 그들의 범위에 효과적으로 지역적입니다.

6.2.2
6 객체 또는 함수 이외의 것으로 선언된 식별자; 함수 파라미터로 선언된 식별자; 스토리지 클래스 지정자 없이 선언된 객체에 대한 블록 범위 식별자;extern.

이들은 동일한 범위에서 재선언할 없습니다(소위 전달 선언 제외)에서 재선언할 수 없습니다.그러나 다른 번역 단위를 포함하여 다른 범위에서 자유롭게 재선언할 수 있습니다.서로 다른 범위에서 완전히 독립적인 유형을 선언할 수 있습니다.예를 들어 두 개의 서로 다른 번역 단위(즉, 두 개의 서로 다른 파일 범위)에서 두 개의 서로 다른 관련 없는 번역 단위를 선언했습니다.struct foo이건 합법적인 겁니다

C. , C 에 .에서는 이 두합니다를 합니다.foo대외적인 연계하여그리고 전체 프로그램에서 외부 링크 기능에 대한 정의를 둘 이상 제공할 수 없습니다.

6.9
5 [...] 외부 연계로 선언된 식별자가 표현에 사용된 경우(a의 피연산자의 일부로서 제외)sizeof아니면_Alignof결과가 정수 상수인 연산자), 전체 프로그램 어딘가에 식별자에 대한 외부 정의가 하나만 있어야 하며, 그렇지 않으면 하나 이상이 없어야 합니다.


C++에서는 연결의 개념이 확장되어 있습니다: 유형을 포함하여 훨씬 더 다양한 개체에 특정 연결을 할당합니다.C++ 클래스에서 유형은 연결이 있습니다.네임스페이스 범위에 선언된 클래스에 외부 연결이 있습니다.그리고 C++의 하나의 정의 규칙은 외부 링크가 있는 클래스가 여러 개의 정의(across 다른 번역 단위)를 가진 경우 이 모든 번역 단위에서 동등하게 정의되어야 한다고 명시적으로 명시합니다(http://eel.is/c++draft/basic.def.odr#12) .그래서, C++에서 당신의struct정의는 불법입니다.

C++ ODR 규칙(본질적으로 C와 동일한 이유로) 때문에 C++에서도 함수 정의가 여전히 유효하지 않습니다.

함수 정의는 둘 다 다음과 같은 엔티티를 선언합니다.foo외부 연관성이 있는 경우, C 표준은 외부 연관성이 있는 개체에 대한 정의가 하나 이상 있어서는 안 된다고 말합니다.정의한 구조 유형은 외부 연결을 가진 도면요소가 아니므로 두 개 이상의 정의를 가질 수 있습니다.struct foo.

외부 링크가 있는 개체를 동일한 이름을 사용하여 선언했다면 이는 오류가 됩니다.

축구의

struct foo {
   int a;
};
struct foo obj;

바의

struct foo {
    char a;
};
struct foo obj;

이제 두 개의 개체가 있습니다.obj둘 다 외부적인 연관성을 가지고 있고, 이것은 허용되지 않습니다.

개체 중 하나가 정의되지 않고 선언만 되어도 잘못된 것입니다.

축구의

struct foo {
   int a;
};
struct foo obj;

바의

struct foo {
    char a;
};
extern struct foo obj;

이것은 정의되지 않았습니다, 왜냐하면 두 개의 선언이obj동일한 개체를 참조하지만 호환되는 유형이 없습니다(왜냐하면).struct foo파일마다 다르게 정의됩니다.

C++에는 설명해야 할 유사하지만 더 복잡한 규칙이 있습니다.inline기능과inline변수, 템플릿 및 기타 C++ 기능을 제공합니다.C++에서 관련 요구 사항은 ODR(One-Definition Rule)이라고 합니다.한 가지 주목할 만한 차이점은 C++가 서로 다른 두 가지를 허용하지도 않는다는 것입니다.struct외부 링크가 있는 개체를 선언하거나 변환 단위 간에 "공유"된 개체를 선언하는 데 사용되지 않는 경우에도 정의.

에 대한 두가지 선언.struct foo멤버의 종류가 같지 않아 서로 호환되지 않습니다.두 개를 혼동하는 행동을 하지 않는 한 각 번역 단위에서 둘 다 사용해도 좋습니다.

예를 들어 이렇게 한 경우:

축구:

struct foo {
   char a;
};

void bar_func(struct foo *f);

void foo_func()
{
    struct foo f;
    bar_func(&f);
}

bar.c:

struct foo {
   int a;
};

void bar_func(struct foo *f)
{
    f.a = 1000;
}

정의되지 않은 행동을 호출하게 되는 이유는struct foo그거bar_func기대는 다음과 호환되지 않습니다.struct foo그거foo_func공급하고 있습니다.

구조물의 호환성은 C 표준의 섹션 6.2.7에 상세하게 설명되어 있습니다.

1 유형이 동일한 경우 두 유형이 호환되는 유형을 갖습니다.두 가지 유형이 호환되는지 여부를 결정하는 추가 규칙은 유형 지정자의 경우 6.7.2, 유형 한정자의 경우 6.7.3 및 선언자의 경우 6.7.6에 설명되어 있습니다.또한 별도의 번역 단위로 선언된 두 개의 구조, 결합 또는 열거형은 태그 및 멤버가 다음 요구 사항을 충족하는 경우 호환됩니다.하나가 태그로 선언된 경우, 다른 하나는 동일한 태그로 선언됩니다.둘 다 각각의 번역 단위 내의 어느 곳에서든 완료된 경우, 다음과 같은 추가 요건이 적용됩니다. 각 해당 구성원 쌍이 호환되는 유형으로 선언되도록 구성원 간에 일대일 대응 관계가 있어야 합니다. 한 쌍의 구성원이 정렬 지정자로 선언된 경우, 다른 한 쌍의 구성원은 i입니다.s는 동등한 정렬 지정자로 선언되며, 쌍의 한 멤버가 이름으로 선언되면 다른 멤버는 동일한 이름으로 선언됩니다.2개의 구조물에 대해서는 동일한 순서로 해당 부재를 선언합니다.두 구조 또는 조합의 경우 해당 비트 필드의 너비가 동일해야 합니다.두 개의 열거에 대해 해당 구성원의 값은 동일해야 합니다.

2 동일한 객체 또는 기능을 언급하는 모든 선언은 호환 가능한 유형을 가져야 합니다. 그렇지 않으면 동작이 정의되지 않습니다.

요약하자면, 두 가지 예는struct foo이름과 유형이 같고 순서가 같은 구성원이 있어야 호환됩니다.

그러한 규칙들은 필요합니다.struct헤더 파일에 한 번 정의할 수 있으며 이후에 여러 원본 파일에 헤더가 포함됩니다.결과적으로 다음과 같습니다.struct여러 소스 파일에 정의되어 있지만 각 인스턴스가 호환됩니다.

이름에 차이가 있는 것이 아니라 이름에 차이가 있습니다. 구조 정의는 어디에도 저장되지 않으며 이름은 컴파일 중에만 존재합니다.
(동일하게 명명된 구조물을 사용할 때 충돌이 발생하지 않도록 하는 것은 프로그래머의 책임입니다.그렇지 않으면, 우리의 오랜 친구인 정의되지 않은 행동이 전화를 걸어 옵니다.)

한편, 함수는 어딘가에 저장될 필요가 있으며, 외부 링크가 있는 경우 링커의 이름이 필요합니다.

당신이 당신의 기능을 만든다면,static이므로 링크 "" 이므로를 하십시오.

링커에서 함수 정의를 숨기려면 static 키워드를 사용합니다.

축구의

    static int foo() {
        return 1;
    }

바의

    static int foo() {
        return 0;
    }

언급URL : https://stackoverflow.com/questions/50590782/struct-vs-function-definitions-in-scope

반응형