精华内容
下载资源
问答
  • C语言结构体与指针

    2018-08-29 15:24:35
    上面代码首先定义了一个书籍的结构体类型,在main函数中声明了一本书A,并设置了页数和价格,接着将本书赋值给了另一本书B,并设置了页数和价格,声明一个指针指向了第一本书,并修改了其值,分别打印书A信息。...
    typedef struct{
        int pages;
        float price;
    }BOOK;
    
    int main(int argc, const char * argv[]) {
    
        BOOK aBook;
        aBook.pages = 300;
        aBook.price = 22.8;
        BOOK bBook = aBook;
        bBook.pages = 400;
        bBook.price = 40.7;
    
        printf("aBook.pages = %d, price = %.2f\n", aBook.pages, aBook.price);
    
        BOOK *pBook = &aBook;
        pBook->pages = 800;
        pBook->price = 60.6;
        printf("aBook.pages = %d, price = %.2f\n", aBook.pages, aBook.price);
        return 0;
    }

    上面代码首先定义了一个书籍的结构体类型,在main函数中声明了一本书A,并设置了页数和价格,接着将本书赋值给了另一本书B,并设置了页数和价格,声明一个指针指向了第一本书,并修改了其值,分别打印书A信息。结果如下:

    aBook.pages = 300, price = 22.80
    aBook.pages = 800, price = 60.60
    Program ended with exit code: 0
    展开全文
  • c语言结构体与指针

    2017-08-27 22:22:57
    结构体:数据经常以组的形式存在,雇主必须声明了每一位雇员的姓名,年龄和工资。如果这些值存储在一起,访问起来会变得简单一些。如果数据类型不同,我们可以用结构来吧不同类型存储起来。 struct tag{ member-list...

    结构体:

    数据经常以组的形式存在,雇主必须声明了每一位雇员的姓名,年龄和工资。如果这些值存储在一起,访问起来会变得简单一些。如果数据类型不同,我们可以用结构来吧不同类型存储起来。

    struct tag{ member-list } variable-list

    结构体有几种写法,例如:

    1.

    struct {
        int a;
        char b;
        float c;
    } x;

    此种写法为匿名结构体(相当于单例),创建了一个x变量,包含3个成员。

    struct {
        int a;
        char b;
        float c;
    } y[10], *z;
    

    创建了y(数组),和z(指针)。

    2.也可以不用声明变量列表。

    struct SIMPLE{
        int a;
        char b;
        float c;
    }

    未来的变量可以这么声明。

    struct SIMPLE x;
    struct SIMPLE y[10],*z;
    1. 3.
    typedef struct{
        int a;
        char b;
        float c;
    } Simple;
    

    注意:typedef的意思是,类型取别名
    例如:

    //Age int类型的别名
    typedef int Age;
    //Age int类型指针的别名
    typedef int* Ap;

    这么声明和声明一个结构标签几乎相同,区别现在simple是一个类名,而不是一个结构体标签。所以后续标签可以是这个样子。

    Simple x;
    Simple y[10], *z;
    

    如果想在多个源文件中使用同一种类型的结构,应该把标签声明和typeof形式声明放在一个头文件中。当源文件需要这个声明的时候,可以用#include 把那个头文件包含进来。

    结构成员的访问

    1. 用“.”访问
      假如一个声明。
    struct COMPLEX comp;
    

    访问sa

    ((comp.sa)[4]).c

    简写

    comp.sa[4].c

    2.用”->”访问
    假如一个函数的参数指向结构的指针。

    void func( struct COMPLEX *P);

    访问这个变量所指向的结构的成员f。

    
    cp->f

    符号“->“就是 “(*cp.)”的简写。

    结构体的自引用

    struct SELF{
        int a;
        struct SELF b;
        int c;
    };

    这种类型是不合法的,因为b是两另一个完整的结构。包含自己的成员b。第二个又是一个完整的结构包含成员b。这样就进行了死循环。
    而我们定义一个指针就是合法的。编译器在结构长度确认之前就已经知道了指针的结构。

    struct SELF{
        int a;
        struct SELF *b;
        int c;
    };

    还有一点需要注意:

    typedef struct{
        int a;
        struct SELF *b;
        int c;
    }SELF;

    这种是不对的。因为SELF到了末尾才定义,之前是没有定义的。
    我们可以在之前加上一个名称来声明b。

    typedef struct SELF_TAG{
        int a;
        struct SELF_TAG *b;
        int c;
    }SELF;

    结构体的初始化

    struct INIT{
        int a;
        short b[10];
        Simple c;
    } x= {
      10,
      {1,2,3,4,5}
      {25,'x',1.9}
    };

    指针与结构体数组遍历

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <Windows.h>
    
    //定义一个结构体。
    struct Man{
        char name[20];
        int age;
    };
    void main(){
        //定义一个结构体数组。并且赋值。
        struct Man mans[] = { {"zhangsan",20}, {"lisi", 19} };
        //遍历结构体数组
        //1.
        struct Man *p = mans;
        for (; p < mans + 2; p++){
            printf("%s,%d\n", p->name, p->age);
        }
    
        //2.
        int i = 0;
        for (; i < sizeof(mans) / sizeof(struct Man); i++){
            printf("%s,%d\n", mans[i].name, mans[i].age);
        }
    
        //(*env)->
    
        system("pause");
    }

    结构体的大小(字节对齐)

    结构体变量的大小,必须是最宽基本数据类型的整数倍。提升读取的效率

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <Windows.h>
    
    struct Man{
        int age;
        double weight;  
    };
    
    void main(){
    
        struct Man m1 = {20,89.0};
        printf("%#x,%d\n", &m1,sizeof(m1));
        getchar();
    }

    结构体与动态内存分配

    
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <Windows.h>
    
    struct Man{
        char *name;
        int age;
    };
    
    void main(){
        //初始化
        struct Man *m_p = (struct Man*)malloc(sizeof(struct Man) * 10);
        struct Man *p = m_p;
        //赋值
        p->name = "Jack";
        p->age = 20;
        p++;
        p->name = "Rose";
        p->age = 20;
    
        struct Man *loop_p = m_p;
        for (; loop_p < m_p + 2; loop_p++){
            printf("%s,%d\n", loop_p->name, loop_p->age);
        }
    
        free(m_p);
        getchar();
    }

    结构体函数指针成员

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <Windows.h>
    
    struct Girl{
        char *name;
        int age;
        //函数指针
        void(*sayHi)(char*);
    };
    //Girl结构体类似于Java中的类,name和age类似于属性,sayHi类似于方法
    void sayHi(char* text){
        MessageBoxA(0, text, "title", 0);
    }
    
    void main(){
        struct Girl g1;
        g1.name = "Lucy";
        g1.age = 18;
        g1.sayHi = sayHi;
    
        g1.sayHi("hello");
    
        getchar();
    }
    typedef struct Girl{
        char *name;
        int age;
        //函数指针
        void(*sayHi)(char*);
    }Girl;
    
    //Girl结构体指针取别名GirlP
    typedef Girl* GirlP;
    
    void sayHi(char* text){
        MessageBoxA(0, text, "title", 0);
    }
    
    //改名
    void rename(GirlP gp1){
        gp1->name = "Lily";
    }
    
    void main(){
        Girl g1 = { "Lucy", 18, sayHi };
        GirlP gp1 = &g1;
        gp1->sayHi("Byebye!");
        //传递指针,改名
        rename(gp1);
    
        getchar();
    }

    联合体

    联合所有成员引用的是内存中的相同位置。当你想在不同时刻把不同的东西存储于同一个位置时,就可以使用联合。

    不同类型的变量共同占用一段内存(相互覆盖),联合变量任何时刻只有一个成员存在,节省内存
    联合体变量的大小=最大的成员所占的字节数

    例如:

    union hold{
        int digit;
        double bigf1;
        char letter;
    }

    我们可以这么定义联合变量.

    union hold fit; //hold类型的联合变量。
    union hold save[10]; //10个联合变量的数组。
    union hold *pu;指向联合变量的指针。
    

    联合的初始化。

    union hold valA;
    valA.letter = 'R';
    union hold valB = valA; //把一个联合初始化为另一个联合。
    union hold valC = {88}; //初始化联合的digit成员。
    union hold valD = {.bigf1 = 118.2} //z指定初始化项目。
    
    展开全文
  • C语言结构体与指针和函数与指针

    千次阅读 2019-01-29 21:55:31
    本篇博文主要介绍结构体、函数和指针的应用 结构体(struct),主要分三个部分 建立结构声明:描述结构如何组合的主要方法,创建一个模板 例如:struct book { char title[MAX]; char author[MAX]; ...

    本篇博文主要介绍结构体、函数和指针的应用

    • 结构体(struct),主要分三个部分

      • 建立结构声明:描述结构如何组合的主要方法,创建一个模板
        • 例如:struct book {
          char title[MAX];
          char author[MAX];
          float value;
          };
        • 这就是一个结构声明,它并没有创建一个实际的数据对象,而是描述了组成这类对象的元素。因为只是声明所以就没有占用内存。
      • 定义结构变量: struct book library;
        • 编译器使用book为模板为该变量分配空间

        • struct book library;是以下声明的简化

        • struct book {
          char title[MAX];
          char author[MAX];
          float value;
          } library;

        • 可以将声明结构和定义结构合并一步:

        • struct {
          char title[MAX];
          char author[MAX];
          float value;
          }library;

      • 初始化结构:
        • struct book library = {
          “C language”,
          “Ronny”,
          2.0
          };
        • 访问结构成员:用结构运算符(.)
        • library.value = 2.0
        • 也可以单独给某个成员赋值:
        • struct book library = {
          .value=2.0
          };
    • 指向结构的指针,声明和初始化结构指针

      • struct book {
        char title[MAX];
        char author[MAX];
        float value;
        };

      • struct book * red;这个声明不是建立一个新的结构,而是意味着指针red可以指向任何有book类型的结构

      • struct book my_book;
        red = &my_book;
        和数组不同,结构体的名字不是该结构的地址,必须使用&运算符

      • 用指针访问成员,运算符(->)

      • my_book.value==(*red).value==red->value

    • 函数和指针

      • 函数是有地址的,因为函数的机器语言实现是由载入到内存的代码组成。指向函数的指针中保存着函数代码起始处的地址
      • 当声明一个数据指针时,必须声明它指向的数据的类型。当声明一个函数指针时,必须声明它指向的函数类型。要指定函数类型,就要指出函数的返回类型以及函数的参量类型。
      • void ToUpper (char *)
      • void ( * pt) (char * )
        从这个声明中看出,第一个圆括号将运算符*和pt结合在一起,这意味着pt是一个指向函数的指针。这样( * pt)是一个函数,并使(char * )作为该函数的参量列表,void作为返回类型
      • 举例几个关于函数指针和函数名之间赋值的例子:
        • void ToUpper (char *);
          void ToLower (char *);
          int round (double);
          void ( * pt) (char *);
          pt = ToUpper ; //合法,ToUpper 是函数ToUpper ()的地址
          pt = ToLower;//合法,ToLower 是函数ToLower ()的地址
          pt = round ;//无效,round是错误类型的函数
          pt = ToUpper ( );//无效ToUpper ( )不是地址
    • 看下实际程序中是如何运用的

    #include<stdio.h>
    #include<stdlib.h>
    
    //声明结构体class
    struct class{
    	unsigned char name;
    	unsigned char number;
    };
    
    //声明结构体school,注意里面还嵌套其他结构体
    struct school{
    
    	struct class east;
    	struct class west;
    
    };
    
    //定义函数,入参是结构体school指针
    int struct_fun(struct school *sh)
    {
    	sh->east.name=1;
    	sh->west.number=2;
    	printf("In struct_fun;\n");
    	return 0;
    }
    //定义一个函数,也是常说的回调函数
    int callback_fun(int z,int h)
    {
    	int k=0;
    	printf("In callback func\n");
    	k=z+h;
    	return k;
    }
    
    //定义函数,参数是函数指针
    int add_func(int (*pt_fun)(int x,int y),int g,int h)
    {
    	int j=0;
    	printf("In add func\n");
    	//传进来的函数指针的使用方法,有两种都可以
    	//j=pt_fun(g,h);
    	j=(*pt_fun)(g,h);
    	return j;
    }
    
    void main()
    {
    	//定义结构school变量
    	struct school cqut;
    	unsigned int a=20,b=30,c=0;
    	//传入结构体地址作为参数
    	struct_fun(&cqut);
    	printf("cqut.east.name %d\tcqut.west.number %d\n",cqut.east.name,cqut.west.number);
    	//函数指针是入参,回调函数
    	c=add_func(callback_fun,a,b);
    	printf("Callback %d\n",c);
    	
    }
    
    
    
    
    展开全文
  • //读取结构体成员的值 printf("%s的学号是%d,年龄是%d,在%c组,今年的成绩是%.1f!\n", (*pstu).name, (*pstu).num, (*pstu).age, (*pstu).group, (*pstu).score); printf("%s的学号是%d,年龄是%d,在%c组,...
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdio.h>
    int main() {
    
        struct {
            char *name;  //姓名
            int num;  //学号
            int age;  //年龄
            char group;  //所在小组
            float score;  //成绩
        } stu1 = { "Tom", 12, 18, 'A', 136.5 }, *pstu = &stu1;
        //读取结构体成员的值
        printf("%s的学号是%d,年龄是%d,在%c组,今年的成绩是%.1f!\n", (*pstu).name, (*pstu).num, (*pstu).age, (*pstu).group, (*pstu).score);
        printf("%s的学号是%d,年龄是%d,在%c组,今年的成绩是%.1f!\n", pstu->name, pstu->num, pstu->age, pstu->group, pstu->score);
    //        printf("%s的学号是%d,年龄是%d,在%c组,今年的成绩是%.1f!\n", pstu.name, pstu.num, pstu.age, pstu.group, pstu.score);go语言可以在指针直接访问元素duck typing
    
    //      数组名代表首地址
    
    
    
    
        int a[5]= {1,2,66,4,5};
    
    //
        printf("fffffff%d----%d",a,*a);
        printf("fffffff%d----%d",a+2,*(a+2));//如此处理的主要是保证数据在空间的有效,否则拆分的数据毫无含义,在整个算法上都不存在必要性
        printf("fffffff%d----%d\n",a,*a);
    
    
    
    
    
    
        //当整数值转换为地址偏移量时,编译器假设只有相同大小的内存位置位于原始地址和地址加上偏移量之间。
    
    
    //此假设对数组成员有效。根据定义,数组是一系列相同类型的值;其元素位于连续的内存位置。但是,除了数组元素之外的任何类型的存储都不能保证由相同类型的标识符填充。也就是说,空白可以出现在内存位置之间,甚至是同一类型的位置之间。因此,除了数组元素之外的任何值的地址的加减结果都是未定义的。
        int array[20]= {0};
        int *ptr=array;
        for(int i=0; i<20; i++) {
            (*ptr)+=i;
            ptr++;//指向下一个元素地址
            printf("%d\n",array[i]);
        }
    
    //    char ap[20]=" You_are_a_girl";
    //    char *p=ap;
    //    char **ptr=&p;
    //    //printf("p=%d\n",p);
    //    //printf("ptr=%d\n",ptr);
    //    //printf("*ptr=%d\n",*ptr);
    //    printf("**ptr=%c\n",**ptr);
    //    ptr++;
    
    
    
    
        ///
    //测试对指定内存地址操作
                int aa[10] ={22};
                printf("a[0]%d\n",aa[0]);
                printf("a[1]%d\n",aa[1]);
                printf("%d\n",&aa);      //函数名==首地址&aa等价于aa
                int *pa =(int *)&aa;//根据打印的数据地址,数据地址转换为指针变量地址........
                printf("pa--%d\n",*pa);//*加指针变量 取指针指向内存变量的值
                int x=*pa;
                pa++;
               int  zz=(*pa)+3;
                printf("zz%d\n",zz);
                int *pa1 =(int *)&aa;
                int y=*pa1;//此处不好理解按照一般思路*pa是内存地址
                printf("??%d\n",x);
                printf("??%d",y);
                return 0;
    }
    
    

    Tom的学号是12,年龄是18,在A组,今年的成绩是136.5!
    Tom的学号是12,年龄是18,在A组,今年的成绩是136.5!
    fffffff6356680----1fffffff6356688----66fffffff6356680----1
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    a[0]22
    a[1]0
    6356560
    pa--22
    zz3
    ??22
    ??22
    Process returned 0 (0x0)   execution time : 0.869 s
    Press any key to continue.

     

     

     

    展开全文
  • //打印结构体成员信息 void printTeacher ( Teacher * p , int n1 , int n2 ) { if ( p == NULL ) { return - 1 ; } int i = 0 , j = 0 ; for ( i = 0 ; i ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,632
精华内容 652
关键字:

c语言结构体与指针

c语言 订阅