01起因上一篇《STM32编程中枚举和结构体的结合》,有读者对下面的代码有疑惑typedefstruct{char*name;//nameintnum;//学号intage;//agefloatscore;//成就}stuff_s;stuff_sxiaoming;voidxiaoming_inf_init(){xiaoming.name="xiaoming";xiaoming.num=1;xiaoming.age=18.0;xiaoming.score=100;}很明显这位读者实现了留言的名字成员是一个指针。当没有为指针分配内存时,直接复制“xiaoming”字符串是错误的。先说结论,这个没问题,下面我会详细解释。02说明首先,实践是检验真理的唯一标准。我们可以直接在编译器中运行代码。这里我使用IAR编译,在VisualStudio中运行的结果是一样的。这里我以IAR为例来看,运行没问题,namemember赋值正常。这里注意name指针指向的位置是0x8002A5C,在flash的地址范围内,也就是编译器直接把“xiaoming”这个字符串作为常量放在flash中,然后给这个指针赋值常量为名字指针,所以不需要提前为名字指针申请内存空间。关于STM32的内存分配,可以看之前的推文《C语言在STM32中的内存分配》。这样写也是合法正确的。当然,最熟悉的方式是:xiaoming.name=(char*)malloc(10);memcpy(xiaoming.name,"xiaoming",8);xiaoming.num=1;xiaoming.age=18.0;xiaoming.score=100;free(xiaoming.name);运行结果如下。可以看出name指针指向的是内存,这与初始代码不同。然后和开头的写法一样,如下:xiaoming.name="xiaoming";编译正常,运行正常。使用上有什么限制吗?答案是肯定的chartest_char;xiaoming.name="xiaoming";test_char=xiaoming.name[2];这样写是正确的,test_char可以正确赋值字符a;但是下面写错了xiaoming.name="xiaoming";xiaoming.name[2]='Q';这样写是可以编译执行的,不报错,但是达不到修改第三个字符的目的。本质上,因为name指针指向的是Flash,所以可以用上面的方法读,但是不能用上面的方法写。如果使用下面的写法,读写操作的操作是没有问题的,因为name指针指向的是内存,具有可读可写的属性。xiaoming.name=(char*)malloc(10);memcpy(xiaoming.name,"xiaoming",8);xiaoming.num=1;xiaoming.age=18.0;xiaoming.score=100;free(xiaoming.name);所以在日常写代码的时候需要注意这些。我的观点是:按照上面的方法,先为指针申请内存,然后再赋值。当然,一切都不是绝对的,要视情况而定。在下面的情况下,你也可以直接给指针赋一个字符串来确认指针不会有写操作,只有读操作,而且你认为加个memcpy语句会影响你的代码。加快速度。确认指针不会有写操作,只有读操作,系统没有多余的内存给指针申请。03const关键字上面说了只读属性,那我们再来说说const关键字。我们先看下面的代码操作)malloc(10);memcpy(xiaoming.name,"xiaoming",8);xiaoming.name[2]='Q';xiaoming.num=1;xiaoming.age=18.0;xiaoming.score=100;free(xiaoming.name);}在指针名前加了const关键字,这段代码根本无法被IAR编译器编译。原因很简单,因为指针名有const属性,不能写。所以,上一节最后部分提到,当你确认指针不会有写操作,只有读操作时,你可以在指针定义前加一个const属性,因为项目代码不是你一个人维护的,你设计的时候认为这个指针只有读操作,加上const,这样别人写访问的时候,直接在IAR报错,不会在产品中留下这个隐患。当然,constchar*name;上面的定义也没有标准化。当指针加上const时,应该体现在指针的名称上。不同的公司有不同的命名约定,每个人都有自己的规范。这不再是演示。本文转载自微信公众号《知乎编程》【编者推荐】Kubernetes容器平台架构解读支付宝应用合集五福版发布:祝福相伴,五福,即将来临!新版Windows1122526修复了很多问题!新功能抢先看WiFi7有多强?三倍于WiFi6,速度如飞Python再次夺得年度编程语言,微软或成最大赢家
