C의 구조체 멤버에 대한 기본값


82

일부 구조체 멤버에 대해 기본값을 설정할 수 있습니까? 다음을 시도했지만 구문 오류가 발생했습니다.

typedef struct
{
  int flag = 3;
} MyStruct;

오류 :

$ gcc -o testIt test.c 
test.c:7: error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘=’ token
test.c: In function ‘main’:
test.c:17: error: ‘struct <anonymous>’ has no member named ‘flag’

구조에 대한 이니셜 라이저 함수를 만들 수 있습니다.
sgarizvi

4
C가 아닙니다. 원하는 값으로 구조체를 반환하는 함수를 만들 수 있습니다.
Vaughn Cato

: 당신이 그것을 만들 때이 같은 값을 초기화 할 수 stackoverflow.com/questions/749180/default-values-in-ac-struct
판타스틱 미스터 폭스

C ++ 구조체의 경우 생성자에서 기본 데이터를 초기화 할 수 있습니다
Zac

답변:


122

구조는 데이터 유형 입니다. 데이터 유형에 값을 제공하지 않습니다. 데이터 유형의 인스턴스 / 객체에 값을 제공합니다.
따라서 C에서는 불가능합니다.

대신 구조 인스턴스에 대한 초기화를 수행하는 함수를 작성할 수 있습니다.

또는 다음을 수행 할 수 있습니다.

struct MyStruct_s 
{
    int id;
} MyStruct_default = {3};

typedef struct MyStruct_s MyStruct;

그런 다음 항상 새 인스턴스를 다음과 같이 초기화하십시오.

MyStruct mInstance = MyStruct_default;

3
글로벌 배열이있는 경우 : 'MyStruct arr [MAX_SIXE];', 함수를 어떻게 사용할 수 있습니까? (참고 : I는 init () 모든 멤버를 통해 이동하고 플래그를 설정합니다 기능을 사용할 수 없습니다)
user1508893

10
MyStruct_default는 const로 선언되어야합니다.
Lundin

1
답변 해 주셔서 감사합니다. 온라인을 테스트하는 코드 샌드 박스를 만들고 결국, 처음에는 모든 것을 연결하는 문제가 있었다이 다른 사람 도움이되기를 바랍니다 : ideone.com/knQ7xS
HoldOffHunger

52

이런 식으로 할 수 없습니다

대신 다음을 사용하십시오.

typedef struct
{
   int id;
   char* name;
}employee;

employee emp = {
.id = 0, 
.name = "none"
};

매크로를 사용 하여 인스턴스 를 정의 하고 초기화 할 수 있습니다 . 이렇게하면 새 인스턴스를 정의하고 초기화 할 때마다 더 쉽게 만들 수 있습니다.

typedef struct
{
   int id;
   char* name;
}employee;

#define INIT_EMPLOYEE(X) employee X = {.id = 0, .name ="none"}

직원 유형으로 새 인스턴스를 정의해야 할 때 코드에서이 매크로를 다음과 같이 호출하면됩니다.

INIT_EMPLOYEE(emp);

1
요구 사항을 충족하지 못하는 매개 변수로 전달하려는 경우 좋지 않은 것 같습니다.

18

C에서 구조를 정의 할 때 초기화 할 수 없다는 Als에 동의합니다. 그러나 아래와 같이 인스턴스 생성시 구조를 초기화 할 수 있습니다.

C에서는

 struct s {
        int i;
        int j;
    };

    struct s s_instance = { 10 ,20 };

C ++에서는 아래와 같이 구조 정의에 직접적인 가치를 부여 할 수 있습니다.

struct s {
    int i;

    s(): i(10)
    {
    }
};

13

넌 할 수있어:

struct employee_s {
  int id;
  char* name;
} employee_default = {0, "none"};

typedef struct employee_s employee;

그런 다음 새 직원 변수를 선언 할 때 기본 초기화를 수행하는 것을 기억해야합니다.

employee foo = employee_default;

또는 팩토리 함수를 통해 항상 직원 구조체를 구축 할 수 있습니다.


8

사용하는 경우 개체 생성에 gcc줄 수 있습니다 designated initializers.

typedef struct
{
   int id=0;
   char* name="none";
}employee;

employee e = 
{
 .id = 0;
 .name = "none";
};

또는 단순히 배열 초기화와 같이 사용하십시오.

employee e = {0 , "none"};


1
이 질문에서 더 많은 코드가 지정된 이니셜 라이저에 콜론을 사용하는 것을 보았습니다. stackoverflow.com/questions/1601201/…
sdaau

7

다른 답변에서 언급했듯이 기본 구조체를 만듭니다.

struct MyStruct
{
    int flag;
}

MyStruct_default = {3};

그러나 위의 코드는 헤더 파일에서 작동하지 않습니다 multiple definition of 'MyStruct_default'. 오류가 발생 합니다.. 이 문제를 해결하려면 extern헤더 파일에서 대신 사용 하십시오.

struct MyStruct
{
    int flag;
};

extern const struct MyStruct MyStruct_default;

그리고 c파일에서 :

const struct MyStruct MyStruct_default = {3};

이것이 헤더 파일에 문제가있는 사람에게 도움이되기를 바랍니다.


몇 년 후 코멘트 : 헤더 파일에서 바로이 작업을 수행 할 수 있다면 더 합리적 일 것입니다.
David Callanan

5

더욱이 기존 답변을 추가하려면 구조체 이니셜 라이저를 숨기는 매크로를 사용할 수 있습니다.

#define DEFAULT_EMPLOYEE { 0, "none" }

그런 다음 코드에서 :

employee john = DEFAULT_EMPLOYEE;

3

초기화 기능을 구현할 수 있습니다.

employee init_employee() {
  empolyee const e = {0,"none"};
  return e;
}

C 구조체 변수 객체 e (const 여부)는 정의 된 블록이 종료 될 때 사라집니다. 포인터 인 경우 댕글 링 포인터 문제가 발생합니다. 따라서 반환 유형이 포인터 인 경우 좋은 솔루션이 아닙니다. 가장 좋은 방법은 C 구조체 이니셜 라이저를 사용하여 기본값이있는 정적 전역 구조체 변수 개체를 갖고 변수에 대한 set 및 get 함수를 사용하여 프로그램 런타임 중에 값을 변경하는 것입니다. 또는 지역 구조체 변수 객체를 매개 변수로 set 함수에 전달하고 set 함수 내에서 속성 값을 변경합니다.
ecle

2
죄송합니다. @ecle이 잘못되었습니다. 반환 값은 포인터가 아닌 네이 키드 구조체입니다. 참조로 반환되지 않고 복사됩니다. 솔직히, 컴파일러는 아마 그것으로부터 도대체 최적화 할 것입니다.
비트 마스크

@bismask 오해하지 마세요 .. 함수가 포인터 인 경우 포인터를 반환하는지 언급 했습니다 . 최근 편집하기 전에 이전 댓글에 댓글을 달았을 수도 있습니다.
ecle

2

다음과 같이 일부 함수를 사용하여 struct를 초기화 할 수 있습니다.

typedef struct
{
    int flag;
} MyStruct;

MyStruct GetMyStruct(int value)
{
    MyStruct My = {0};
    My.flag = value;
    return My;
}

void main (void)
{
    MyStruct temp;
    temp = GetMyStruct(3);
    printf("%d\n", temp.flag);
}

편집하다:

typedef struct
{
    int flag;
} MyStruct;

MyStruct MyData[20];

MyStruct GetMyStruct(int value)
{
    MyStruct My = {0};
    My.flag = value;
    return My;
}

void main (void)
{
    int i;
    for (i = 0; i < 20; i ++)
        MyData[i] = GetMyStruct(3);

    for (i = 0; i < 20; i ++)
        printf("%d\n", MyData[i].flag);
}

2
글쎄, 내가 구조체의 전역 배열을 원한다면 어떻게 GetMyStruct () 호출을 제안합니까?
user1508893

GetMyStruct는 malloc을 사용하지 않아야합니까?
Dmitry


1

이 구조를 한 번만 사용하는 경우 , 즉 전역 / 정적 변수를 생성하면 typedef이 변수를 즉시 제거 하고 초기화 할 수 있습니다 .

struct {
    int id;
    char *name;
} employee = {
    .id = 0,
    .name = "none"
};

그런 다음 그 employee후에 코드에서 사용할 수 있습니다 .


0

구조체에 대한 초기화 함수는 기본값을 부여하는 좋은 방법입니다.

Mystruct s;
Mystruct_init(&s);

또는 더 짧게 :

Mystruct s = Mystruct_init();  // this time init returns a struct

글로벌 배열이있는 경우 : 'MyStruct arr [MAX_SIXE];', 함수를 어떻게 사용할 수 있습니까? (참고 : I는 init () 모든 멤버를 통해 이동하고 플래그를 설정합니다 기능을 사용할 수 없습니다)
user1508893

0

기본값에 대한 또 다른 접근 방식입니다. 구조체와 동일한 유형으로 초기화 함수를 만듭니다. 이 방법은 큰 코드를 별도의 파일로 분할 할 때 매우 유용합니다.

struct structType{
  int flag;
};

struct structType InitializeMyStruct(){
    struct structType structInitialized;
    structInitialized.flag = 3;
    return(structInitialized); 
};


int main(){
    struct structType MyStruct = InitializeMyStruct();
};

0

이에 대한 함수를 만들 수 있습니다.

typedef struct {
    int id;
    char name;
} employee;

void set_iv(employee *em);

int main(){
    employee em0; set_iv(&em0);
}

void set_iv(employee *em){
    (*em).id = 0;
    (*em).name = "none";
}

0

구조체가 허용하는 경우 또 다른 접근 방식은 내부에 기본값이있는 #define을 사용하는 것입니다.

#define MYSTRUCT_INIT { 0, 0, true }

typedef struct
{
    int id;
    int flag;
    bool foo;
} MyStruct;

사용하다:

MyStruct val = MYSTRUCT_INIT;

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.