c++ 1.指针和结构体

本文深入解析C++中的指针运算符、结构体定义及使用,包括取地址和间接寻址运算符,结构体与typedef的使用,以及指向结构体的指针操作。通过实例展示了如何在C++中管理和操作结构体数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、指针运算符

C++ 提供了两种指针运算符,一种是取地址运算符 &,一种是间接寻址运算符 *

& 是一元运算符,返回操作数的内存地址。例如,如果 var 是一个整型变量,则 &var 是它的地址。该运算符与其他一元运算符具有相同的优先级,在运算时它是从右向左顺序进行的。 & 运算符读作"取地址运算符",这意味着,&var 读作"var 的地址"。

间接寻址运算符 *,它是 & 运算符的补充。* 是一元运算符,返回操作数所指定地址的变量的值。

箭头运算符与点运算符有关,对于一个指针ptr,表达式ptr->mem等价于(*ptr).mem;

string s1 = "a string",*p = &s1;
auto n = s1.size();//运行string对象s1的size()成员
n = (*p).size();//运行p所指对象的size成员
n = p->size(;)//等价于(*p).size
//点运算符针对对象和对象的成员,箭头运算符针对的是指针和成员;
#include <iostream>
 
using namespace std;
 
int main ()
{
   int  var;
   int  *ptr;
   int  val;

   var = 3000;

   // 获取 var 的地址
   ptr = &var;//ptr存放取出来的地址

   // 获取 ptr 的值
   val = *ptr;//*寻找地址的内容,存放在val中

   cout << "Value of var :" << var << endl;
   cout << "Value of ptr :" << ptr << endl;
   cout << "Value of val :" << val << endl;

   return 0;
}

//编译结果
Value of var :3000
Value of ptr :0xbff64494
Value of val :3000

 

二、typedef struct和struct

(此处博客链接https://www.cnblogs.com/qyaizs/articles/2039101.html以及参考c语言中文网)

1.在C中定义一个结构体类型要用typedef:
    typedef struct Student
    {
    int a;
    }Stu;
    于是在声明变量的时候就可:Stu stu1;(如果没有typedef就必须用struct Student stu1;来声明) 

             这里的Stu实际上就是struct Student的别名。Stu==struct Student
    另外这里也可以不写Student(于是也不能struct Student stu1;了,必须是Stu stu1;)

 

 c语言使用例子:

(char* 是声明一个字符类型的指针。比如:chat*  y;就是声明一个指针y,这个指针指向的地址上只能存放字符类型的值。

指针即为地址,指针几个字节跟语言无关,而是跟系统的寻址能力有关。比如以前是16位系统,指针即为2个字节,现在一般是32位系统,所以是4个字节)

如果只需要 stu1、stu2 两个变量,后面不需要再使用结构体名定义其他变量,那么在定义时也可以不给出结构体名,如下所示:

struct{  //没有写 stu
    char *name;  //姓名
    int num;  //学号
    int age;  //年龄
    char group;  //所在学习小组
    float score;  //成绩
} stu1, stu2;
//这样做书写简单,但是因为没有结构体名,后面就没法用该结构体定义新的变量

struct stu{
    char *name;  //姓名
    int num;  //学号
    int age;  //年龄
    char group;  //所在学习小组
    float score;  //成绩
} stu1, stu2;
//声明一个变量用 struct stu stu1
#include <stdio.h>
int main(){
    struct{
        char *name;  //姓名
        int num;  //学号
        int age;  //年龄
        char group;  //所在小组
        float score;  //成绩
    } stu1;
    //给结构体成员赋值
    stu1.name = "Tom";
    stu1.num = 12;
    stu1.age = 18;
    stu1.group = 'A';
    stu1.score = 136.5;
    //读取结构体成员的值
    printf("%s的学号是%d,年龄是%d,在%c组,今年的成绩是%.1f!\n", stu1.name, stu1.num, stu1.age, stu1.group, stu1.score);
    return 0;
}

//也可以在定义时整体赋值
struct{
    char *name;  //姓名
    int num;  //学号
    int age;  //年龄
    char group;  //所在小组
    float score;  //成绩
} stu1, stu2 = { "Tom", 12, 18, 'A', 136.5 };

   但在c++里很简单,直接
    struct Student
    {
    int a;
    };    
    于是就定义了结构体类型Student,声明变量时直接Student stu2;

c++使用

#include <iostream>
#include <cstring>
 
using namespace std;
 
// 声明一个结构体类型 Books 
struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
};
 
int main( )
{
   Books Book1;        // 定义结构体类型 Books 的变量 Book1
   Books Book2;        // 定义结构体类型 Books 的变量 Book2
 
   // Book1 详述
   strcpy( Book1.title, "C++ 教程");
   strcpy( Book1.author, "Runoob"); 
   strcpy( Book1.subject, "编程语言");
   Book1.book_id = 12345;
 
   // Book2 详述
   strcpy( Book2.title, "CSS 教程");
   strcpy( Book2.author, "Runoob");
   strcpy( Book2.subject, "前端技术");
   Book2.book_id = 12346;
 
   // 输出 Book1 信息
   cout << "第一本书标题 : " << Book1.title <<endl;
   cout << "第一本书作者 : " << Book1.author <<endl;
   cout << "第一本书类目 : " << Book1.subject <<endl;
   cout << "第一本书 ID : " << Book1.book_id <<endl;
 
   // 输出 Book2 信息
   cout << "第二本书标题 : " << Book2.title <<endl;
   cout << "第二本书作者 : " << Book2.author <<endl;
   cout << "第二本书类目 : " << Book2.subject <<endl;
   cout << "第二本书 ID : " << Book2.book_id <<endl;
 
   return 0;
}

2.

在c++中如果用typedef的话,又会造成区别:
    struct   Student  
    {  
    int   a;  
    }stu1;//stu1是一个变量  

 
    typedef   struct   Student2  
    {  
    int   a;  
    }stu2;//stu2是一个结构体类型=struct Student  

 
    使用时可以直接访问stu1.a
    但是stu2则必须先   stu2 s2;
    然后               s2.a=10;

3.结构体是一种自定义的数据类型,是创建变量的模板,不占用内存空间;结构体变量才包含了实实在在的数据,需要内存空间来存储

4.理论上讲结构体的各个成员在内存中是连续存储的,和数组非常类似,例如上面的结构体变量 stu1、stu2 的内存分布如下图所示,共占用 4+4+4+1+4 = 17 个字节

但是在编译器的具体实现中,各个成员之间可能会存在缝隙,对于 stu1、stu2,成员变量 group 和 score 之间就存在 3 个字节的空白填充(见下图)。这样算来,stu1、stu2 其实占用了 17 + 3 = 20 个字节。

三、指向结构体的指针

结构体变量的指针就是该变量那个所占据的内存段的起始地址。可以设一个指针变量,来指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址

 

创建的对象 stu 在栈上分配内存,需要使用 获取它的地址,例如:Student stu;Student *pStu = &stu;

pStu 是一个指针,它指向 Student 类型的数据,也就是通过 Student 创建出来的对象

 

你也可以在堆上创建对象,这个时候就需要使用前面讲到的new关键字:

          Student *pStu = new Student;

在栈上创建出来的对象都有一个名字,比如 stu,使用指针指向它不是必须的。但是通过 new 创建出来的对象就不一样了,它在堆上分配内存,没有名字,只能得到一个指向它的指针,所以必须使用一个指针变量来接收这个指针,否则以后再也无法找到这个对象了,更没有办法使用它。也就是说,使用 new 在堆上创建出来的对象是匿名的,没法直接使用,必须要用一个指针指向它,再借助指针来访问它的成员变量或成员函数。

栈内存是程序自动管理的,不能使用 delete 删除在栈上创建的对象;堆内存由程序员管理,对象使用完毕后可以通过 delete 删除。在实际开发中,new 和 delete 往往成对出现,以保证及时删除不再使用的对象,防止无用内存堆积

有了对象指针后,可以通过箭头->来访问对象的成员变量和成员函数,这和通过结构体指针(http://c.biancheng.net/view/246.html)来访问它的成员类似,请看下面的示例:

pStu -> name = "小明";
pStu -> age = 15;
pStu -> score = 92.5f;
pStu -> say();
//完整例子
#include <iostream>
using namespace std;
class Student{
public:
    char *name;
    int age;
    float score;
    void say(){
        cout<<name<<"的年龄是"<<age<<",成绩是"<<score<<endl;
    }
};
int main(){
    Student *pStu = new Student;
    pStu -> name = "小明";
    pStu -> age = 15;
    pStu -> score = 92.5f;
    pStu -> say();
    delete pStu;  //删除对象
    return 0;
}

 

<think>嗯,用户问的是如何在C++中用指针创建结构体变量。首先,我需要回忆一下结构体指针的基本概念。结构体是用户自定义的数据类型,可以包含多个不同类型的成员。指针则是用来存储内存地址的变量。 那用指针创建结构体变量的话,应该涉及到动态内存分配,也就是使用new操作符。用户可能想知道如何声明结构体,然后用指针来分配内存并访问成员。不过我得确认步骤是否正确。 首先,定义结构体类型,比如struct Person,包含一些成员变量,比如nameage。然后,用new来动态分配内存,返回一个指向该结构体指针。这时候需要用箭头操作符->来访问成员,或者先解引用再用点操作符。 不过用户可能对动态内存管理的细节不太清楚,比如需要delete释放内存,避免内存泄漏。这部分也需要提到,否则可能会让程序有问题。另外,可能需要比较结构体变量指针的不同访问方式,比如用点号箭头操作符的区别。 还有,是否应该提到使用智能指针?比如C++11之后的unique_ptr或shared_ptr,这样更安全。但用户的问题可能更基础,所以先讲基本的newdelete,再稍微提一下智能指针作为扩展。 可能需要举例说明,先定义结构体,然后动态分配,访问成员,最后释放内存。步骤清晰的话,用户更容易理解。同时要注意语法是否正确,比如结构体定义后的分号,new返回的指针类型是否正确。 有没有可能用户混淆了结构体指针其他类型的指针?可能需要强调结构体指针的声明方式,比如Person *ptr = new Person;。同时,检查是否存在常见错误,比如忘记释放内存,或者访问已经释放的内存。 总结一下,回答的步骤应该是: 1. 定义结构体类型。 2. 使用new运算符动态创建结构体实例,并获取指针。 3. 通过指针访问结构体成员。 4. 使用delete释放内存。 5. 可选:介绍智能指针。 需要确保每个步骤都有示例代码,并解释清楚箭头操作符解引用的用法。可能还需要提醒用户注意内存管理的重要性,避免泄漏。</think>在 C++ 中使用指针创建结构体变量需要结合动态内存分配,以下是详细步骤说明: --- ### 1️⃣ **定义结构体类型** ```cpp struct Student { int id; std::string name; float score; }; // 注意结尾的分号 ``` --- ### 2️⃣ **通过指针动态创建结构体** 使用 `new` 运算符在堆内存中分配结构体空间: ```cpp Student* pStudent = new Student; // 创建指针并分配内存 ``` --- ### 3️⃣ **访问结构体成员** 通过 `->` 运算符或解引用后使用 `.` 访问: ```cpp // 方法1:箭头运算符 pStudent->id = 1001; pStudent->name = "张三"; pStudent->score = 92.5; // 方法2:解引用后使用点运算符 (*pStudent).id = 1002; // 注意括号优先级 ``` --- ### 4️⃣ **内存释放** 必须用 `delete` 释放动态分配的内存: ```cpp delete pStudent; // 释放内存 pStudent = nullptr; // 避免悬空指针 ``` --- ### 5️⃣ **完整示例** ```cpp #include <iostream> #include <string> struct Student { int id; std::string name; float score; }; int main() { // 动态创建结构体 Student* p = new Student{101, "李四", 85.5}; // 修改成员值 p->score += 5.0; // 输出结果 std::cout << "学号:" << p->id << "\n姓名:" << p->name << "\n分数:" << p->score; delete p; // 释放内存 return 0; } ``` --- ### ✨ **技术要点** - **内存管理**:动态分配的内存必须手动释放,否则会导致内存泄漏 - **访问方式对比**: ```cpp (*ptr).member // 解引用后使用点运算符 ptr->member // 直接使用箭头运算符(更简洁) ``` - **智能指针方案(C++11+)**: ```cpp #include <memory> auto sp = std::make_unique<Student>(); // 自动管理内存 sp->id = 2001; ``` --- 通过指针操作结构体可以实现动态内存管理,但需要注意资源释放问题。对于现代 C++ 开发,推荐使用智能指针替代原生指针以提高安全性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值