示例
#include <stdio.h>
void main(){
struct student{
char name[10];
int age;
char *xiaoming;
}stu1={"豪哥",23,"zz"},*p;
p = &stu1;
//struct student stu2= {"豪哥",23};
printf("结构体指针变量p的姓名是:%s,年龄是:%d,小名是:%s\n",p->name,p->age,p->xiaoming);
}
结构体的成员名的访问可以通过:
结构体变量名.成员名
指针结构体的成员名的访问可以通过:
(1)、 (*结构体指针变量名).成员名
(2)、 结构体指针变量名 -> 成员名 //最常用的方式
关于第一种,由于(*p)表示指向结构体的变量,相当于stu1,因此,(*p).name相当于stu1.name,表示p指向结构体变量中成员name。
另外(*p)加一个括号的原因,是因为成员运算符“ . ” 的优先级高于取内容运算符 “ * ” ,不加括号的话就相当于是 * (p.name),这种方法是错误的。
7.2.2、返回指针的函数
定义返回指针的函数很简单,只需要定义时在函数名前加一个指针运算符 " * "即可。定义如下:
类型名 * 函数名(参数列表)
{…}
定义一个返回char* 的函数,返回字符串s 从n1- n2 下标的字符:
(1)、形参s 使用只读限定符const,表示该变量为只读变量,其值不允许被修改。通常采用这种方式对程序中用到的一些固定参数加以限定,防止误修改。
const 省略也能编译通过,只是编程时对确定不能修改的量最好设置为只读(const),这样如果程序中对其进行了修改,编译的时候就会发现。
(2)、substr函数中定义数组a时,static不能省略,因为省略后,数组a默认的存储属性为auto类型,存放在动态存储区,其生命周期仅限于本函数,返回主函数后,数组a所占用的存储空间就释放了。将其存储属性设为静态(static)后,数组a存放在静态存储区中,在整个程序运行期间始终存在。
(3)、下列函数定义的时候也可以不返回指针变量p,可以直接返回数组名a;
#include <stdio.h>
char* substr(const char*,int,int);
void main(){
printf("结构体指针变量p的姓名是:%s,年龄是:%d,小名是:%s\n",p->name,p->age,p->xiaoming);
char *pa = "haogexueCyuyan";
char *sub;
sub = substr(pa,2,4);
printf("返回指针的函数:%s\n",sub);
}
char* substr(const char * s,int n1,int n2){
static char a[80];
char *p =a;
int j=0;
for(int i =n1;i<=n2;i++,j++){
a[j] = s[i];
printf("substr********,a[j]=%c\n",a[j]);
}
a[j] = '\0';
return p;
}
substr********,a[j]=o
substr********,a[j]=g
substr********,a[j]=e
返回指针的函数:oge
7.5、动态内存分配
之前在函数部分讲解时提到过变量的存储属性,其中全局变量和静态局部变量都存放在静态存储区,自动变量存放在动态存储区,还有一部分自由存储区没有讲到,这里C语言中中提供的一组内存管理函数,可以根据用户的需要动态分配内存空间,用完之后也可以随时释放这些空间,此时所分配的内存空间就位于自由存储区。
C语言编程时定义数组必须明确的说明其大小,实际编程的时候经常最初的时候数组的大小不能预料,太大了浪费内存空间,太小了系统无法处理,所以最好就是使用动态内存分配的方式。
这里注意上述函数中返回void *类型并不是函数调用之后无返回值,而是返回一个基类型为void 的指针,它指向所分配存储区的首地址。使用时需要根据实际情况,采用强制类型转化方法将其转换为所赋值指针的类型。