본문 바로가기

Programming/Data Structure

[리눅스][C언어] 구조체 구현

반응형

구조체

데이터타입은 레고블럭과 같은 개념이다.

그런데 이러한 데이터타입을 조합해서 새로운 타입을 만들어낼 수 있는데, struct 구조체다.

 

다양한 데이터타입을 가지고 이러한 새로운 레고블럭을 만들 수 있다는 개념으로 이해하면 된다.

 

 

#include <stdio.h>
#include <string.h> // printf에서 string 포맷을 사용

struct student{
        int s_id;
        char name[20];



};

int main(){

        struct student st1; // 구조체 선언

        st1.s_id = 10;
        strcpy(st1.name, "Lazy Dev");

        printf("s_id : %d\n",st1.s_id);
        printf("name : %s\n",st1.name);



        return 1;

}
root@DESKTOP-O5CM2RJ:/project/22-c_study/04-14# gcc test.c
root@DESKTOP-O5CM2RJ:/project/22-c_study/04-14# ./a.out
s_id : 10
name : Lazy Dev

자바 클래스는 스트럭처에서 파생된 것이다.

 

 

 typedef으로 줄이기

#include <stdio.h>
#include <string.h> // printf에서 string 포맷을 사용

typedef struct student{
        int s_id;
        char name[20];



} stu ;




int main(){

        stu st1; // 구조체 선언

        st1.s_id = 10;
        strcpy(st1.name, "Lazy Dev");

        printf("s_id : %d\n",st1.s_id);
        printf("name : %s\n",st1.name);



        return 1;

}

 

함수 호출하기

일반변수로 호출하기

일반변수 포인터변수

#include <stdio.h>
#include <string.h> // printf에서 string 포맷을 사용

typedef struct student{
        int s_id;
        char name[20];



} stu;



int main(){
        stu st1;

        stu_func(st1);

        return 1;
}



void stu_func(stu st){

        st.s_id = 10;
        strcpy(st.name, "Lazy Dev");

        printf("s_id : %d\n",st.s_id);
        printf("name : %s\n",st.name);

}

 

 

포인터 변수로 호출하기

 

 

#include <stdio.h>
#include <string.h> // printf에서 string 포맷을 사용

typedef struct student{
        int s_id;
        char name[20];



} stu;



int main(){
        stu st1;

        stu_func(&st1);

        return 1;
}



void stu_func(stu * st){

        st->s_id = 10;
        strcpy(st->name, "Lazy Dev");

        printf("s_id : %d\n",st -> s_id);
        printf("name : %s\n",st -> name);

}

 

 

배열과 구조체에서의 변수 주소값 사용법이 다르다?

#include <stdio.h>
#include <string.h> // printf에서 string 포맷을 사용

typedef struct student{
        int s_id;
        char name[20];



} stu;





int main(){
        stu st1;// 스트럭처 변수 선언

        stu_func(&st1); //함수 호출

        printf("s_id2 : %d\n",st1.s_id);
        printf("name2 : %s\n",st1.name);

        printf("st1   : %ld\n",st1);
        printf("&st1  : %ld\n",&st1);

        char a[20];
        printf("a     : %ld\n",a);
        printf("&a    : %ld\n",&a);
        printf("&a[0] : %ld\n",&a[0]);





        return 1;
}



void stu_func(stu * st){

        st->s_id = 10;
        strcpy(st->name, "Lazy Dev");

        printf("s_id  : %d\n",st -> s_id);
        printf("name  : %s\n",st -> name);

}
s_id  : 10
name  : Lazy Dev
s_id2 : 10
name2 : Lazy Dev
st1   : 140736456979040
&st1  : 140736587693248
a     : 140736587693280
&a    : 140736587693280
&a[0] : 140736587693280

배열로 선언된 a의 경우는 &a, &a[0]의 주소가 같을 뿐만 아니라, a의 변수주소마저 동일하다.

 

그런데, 구조체로 선언된 st1의 경우는 달랐다. st1에 들어있는 값은 무슨 주소를 나타내고 있는 것일까?

 

구조체의 주소인 &st1과

구조체의 첫 인자에 해당하는 &st1.s_id의 주소와 같다.

이는 배열과 같다.

 

 

화살표의 정체 ->

포인터를 접근하는 방법으로 (.)은 사용할 수가 없고, (*)의 경우도 연산자이므로 사용할 수가 없었다.

포인터에 대한 접근방법으로 채택한 것이 (->)인 것이다.

 

 

 

C언어의 상속?

typedef struct human{
        char name[20];
        int age;
        char gender;

}human;


typedef struct student{
        int s_id;
        human man; //상속받는 느낌으로도 사용가


} stu;
#include <stdio.h>
#include <string.h> // printf에서 string 포맷을 사용




typedef struct human{
        char name[20];
        int age;
        char gender;

}human;


typedef struct student{
        int s_id;
        human man; //상속받는 느낌으로도 사용가능      


} stu;



int main(){
        stu st1;// 스트럭처 변수 선언

//      stu_func(&st1); //함수 호출

        st1.s_id = 10;
        strcpy(st1.man.name, "Lazy Dev");
        st1.man.age = 25;
        st1.man.gender = 'm';


        printf("st1.s_id : %d\n",st1.s_id);
        printf("st1.man.name : %s\n",st1.man.name);
        printf("st1.man.age : %d\n",st1.man.age);
        printf("st1.man.gendr : %c\n",st1.man.gender); 

        return 1;
}
root@DESKTOP-O5CM2RJ:/project/22-c_study/04-14# gcc test.c
root@DESKTOP-O5CM2RJ:/project/22-c_study/04-14# ./a.out
st1.s_id : 10
st1.man.name : Lazy Dev
st1.man.age : 25
st1.man.gendr : m

 

 

포인터를 활용한 함수

#include <stdio.h>
#include <string.h> // printf에서 string 포맷을 사용




typedef struct human{
        char name[20];
        int age;
        char gender;

}human;


typedef struct student{
        int s_id;
        human man; //상속받는 느낌으로도 사용가능      


} stu;



int main(){
        stu st1;// 스트럭처 변수 선언


        stu_func(&st1); //함수 호출


        return 1;
}



void stu_func(stu * st){

        st->s_id = 10;
        strcpy(st->man.name, "Lazy Dev");


        printf("s_id  : %d\n",st -> s_id);
        printf("name  : %s\n",st -> man.name);
}
root@DESKTOP-O5CM2RJ:/project/22-c_study/04-14# ./a.out
s_id  : 10
name  : Lazy Dev

 

포인터로만 하려면?

#include <stdio.h>
#include <string.h> // printf에서 string 포맷을 사용




typedef struct human{
        char name[20];
        int age;
        char gender;

}human;


typedef struct student{
        int s_id;
        human * man; // 포인터로 선언


} stu;



int main(){
        stu st1;// 스트럭처 변수 선언
        human hm; // student 구조체에서 직접 구현하지 >않고 포인터로 가리켰기 때문에, 여기에서 구조체를 선언해줘야 한다.
        st1.man = &hm; //실제로 human 구조체가 여기에서 구현되고, 구현된 hm 주소를 st1.man에 할당한다.


        stu_func(&st1); //함수 호출


        return 1;
}



void stu_func(stu * st){

        st->s_id = 10;
        strcpy(st -> man -> name, "Lazy Dev");


        printf("s_id  : %d\n",st -> s_id);
        printf("name  : %s\n",st -> man -> name);
}

자바의 객체 생성 개념을 이해하면 왜 메인함수에서 다시 human hm을 선언하고, 주소까지 할당해야 하는 지를 알 수 있다.

반응형