目录
一. 指针数组作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语言——指针初阶(一)_c语言指针p和*p区别-CSDN博客
C语言函数递归经典题型——汉诺塔问题_汉诺(hanoi)塔问题-CSDN博客