C语言——字符串指针变量与字符数组(易错分析)

发布于:2024-12-18 ⋅ 阅读:(10) ⋅ 点赞:(0)

目录

一. 指针数组作main函数

二. 字符指针变量和指针数组

···两者在函数调用栈释放中的应用

        对比下面的两段代码:

        第一段代码运行结果:

        第二段代码运行结果:

使用字符指针变量和字符数组的比较

往期回顾:


一. 指针数组作main函数

        首先我们先补充一个知识点:

二. 字符指针变量和指针数组

        字符串的定义自动包含一个指针(指针常量)char message1[81];为81个字符保留存储空间,并自动创建一个指针常量message1,其中包含message1[0]的地址。

        也可以使用指针char *message2;现在,可以执行赋值语句,例如message2 = "this is a string";不能使用赋值操作符复制字符串。

        下面的声明有效:char *message = "abcdef";
        但是,这不是:char *message;/*指针声明*/ strcpy(message,"abcdef");/*无效拷贝*/
        该策略在这里无效,因为指针的声明仅为一个值(地址)保留了足够的空间。

        char message1[81] = "this is a string;(message1的地址与this is a string的地址无关,message1=&message1[0])

        char *message2 = “this is a string”;(字符串名message2地址就是this is a string的地址)。

···两者在函数调用栈释放中的应用

        对比下面的两段代码:
char* GetMemory(void)
{
	char *p = "hello world";
	return p;
}
int main()
{
	char* str = NULL;
	str = GetMemory();
	printf(str);
}
char* GetMemory(void)
{
	char p[] = "hello world";
	return p;
}
int main()
{
	char* str = NULL;
	str = GetMemory();
	printf(str);
}
        第一段代码运行结果:

        第二段代码运行结果:

        我们来观察这两个代码,其中第一个代码*p指向一个常量字符串,而常量字符串存放在常量区,函数运行完出了作用域,常量区不释放,因此能返回p。

        但是我们来看第二段代码,p表示数组,存在函数栈区,函数运行完出了作用域,栈区释放,返回地址也就没用了,此时返回的指针就变成了悬空指针,再通过这个指针去访问内存(如在main函数中使用printf输出)就会导致未定义行为,可能出现程序崩溃或者输出乱码等错误情况。

        改写方法,可以在函数里面用malloc函数在堆区开辟一段空间,然后在主函数用free函数释放。也可以用static修饰,来把它放在静态区。

        比如:

char* GetMemory(void)
{
	static char p[] = "hello world";
	return p;
}
int main()
{
	char* str = NULL;
	str = GetMemory();
	printf(str);
}

运行结果:

#include <stdio.h>
#include <stdlib.h>

char* GetMemory(void)
{
    char* p = (char*)malloc(12 * sizeof(char));  // 为字符串分配足够的内存空间,包含'\0'
    if (p == NULL) {  // 判断内存分配是否成功
        return NULL;
    }
    strcpy(p, "hello world");  // 将字符串复制到分配的内存空间中
    return p;
}

int main()
{
    char* str = NULL;
    str = GetMemory();
    if (str!= NULL) {
        printf("%s", str);
        free(str);  // 释放通过malloc申请的内存空间
        str = NULL;  // 将指针置空,避免产生野指针
    }
    return 0;
}
  • 使用malloc函数动态分配内存,这里为字符串 "hello world" 分配足够的内存空间,字符串长度为 11 个字符,再加上字符串结束标志 '\0',总共需要 12 个 char 类型的字节空间,所以调用 malloc(12 * sizeof(char))。同时将返回的 void* 类型指针强制转换为 char* 类型指针并赋值给 p
  • 通过 if (p == NULL) 判断内存分配是否成功,如果 malloc 函数未能成功分配内存(返回 NULL),则直接返回 NULL,避免后续出现对无效内存的操作。
  • 使用 strcpy 函数将常量字符串 "hello world" 复制到通过 malloc 分配好的内存空间中,使得这块内存中存储了正确的要输出的字符串内容。
  • 在调用 GetMemory 函数获取字符串指针后,通过 if (str!= NULL) 判断返回的指针是否有效(即内存分配成功),如果有效才进行后续操作,避免对可能为 NULL 的指针进行解引用导致程序出错。
  • 使用 printf("%s", str) 按照字符串格式输出获取到的字符串内容。
  • 调用 free(str) 函数释放之前通过 malloc 申请的内存空间,避免内存泄漏。这是因为动态分配的内存需要手动释放,否则这块内存会一直被占用,直到程序结束,多次这样的情况发生可能导致内存资源耗尽等问题。
  • 最后将 str 指针置为 NULL,这样可以避免后续不小心再次使用这个指针访问已经释放的内存(即产生野指针的情况),增强程序的健壮性。

使用字符指针变量和字符数组的比较

        用字符数组和字符指针变量都能实现字符串的存储和运算,但它们二者之间是有区别的,不应混为一谈,主要有以下几点。

        存储单元的内容,编译时为字符数组分配若干存储单元,以存放各元素的值,而对字符指针变量,只分配一个存储单元。

         char *a; scanf(“%s”,a);  

         char *a,str[10];              

         a=str;                 

         scanf (“%s”,a);     

         指针变量的值是可以改变的,而数组名代表一个固定的值(数组首元素的地址),不能改变。

        字符数组中各元素的值是可以改变的,但字符指针变量指向的字符串常量中的内容是不可以被取代的。

char a[]=”House”,*b=” House”;

a[2]=’r’;       

char a[]=”House”,*b=”House”;

b[2]=’r’;       

本期内容就到这里~~~。

往期回顾:

C语言——习题练习(一)-CSDN博客

C语言——指针初阶(三)-CSDN博客

C语言——指针初阶(二)-CSDN博客

C语言——海龟作图(对之前所有内容复习)_海龟编程语言-CSDN博客

C语言——指针初阶(一)_c语言指针p和*p区别-CSDN博客

C语言函数递归经典题型——汉诺塔问题_汉诺(hanoi)塔问题-CSDN博客

C语言——数组基本知识(二)_c语言四维数组的使用方法-CSDN博客

C语言——数组基本知识(一)-CSDN博客

C语言——数组逐元素操作练习-CSDN博客


网站公告

今日签到

点亮在社区的每一天
去签到