指针和字符数组学习

文章详细对比了C语言中的gets()和puts()函数在处理字符串时的不同,以及字符指针和字符数组的区别。gets()用于从键盘接收字符串,puts()则直接输出字符串。字符数组是固定大小的存储空间,而指针变量存储的是地址,可以动态改变。文章强调了对指针变量和字符数组的正确使用,特别是指针的安全性问题和数组的不可变性。


指针与字符串搞得我有点混乱所以自己梳理 一下

gets()与puts()函数

puts(字符数组)函数:直接输出字符串

#include<stdio.h>
#include<windows.h>
int main()
{
    char *arr;
    arr="hello world";
    puts(arr);
    puts("chi\na");
    printf("%s\n",arr);
    system("pause");
}

在这里插入图片描述

直接输入字符数组名也可以
中间可以包括转义字符
结尾自动换行

gets(字符数组)函数:从键盘得到一个字符串并给到字符数组,并且得到一个函数值,该函数值是字符数组的起始地址

#include <stdio.h>

int main()
{
   char str[50];
   printf("请输入一个字符串:");
   gets(str);
   printf("您输入的字符串是:%s", str);
   char str[]="china";
   char *a=gets(str);
   printf("%p\n",a);
   printf("%p\n",a+1);
   return(0);
}
#------运行结果---------
请输入一个字符串:runoob
您输入的字符串是:runoob
hhhh
000000000061FE0A
000000000061FE0B

gets()不能用于指针变量

通过指针引用字符串

#include<stdio.h>
#include<windows.h>
int main()
{
    char str[10];
    char *arr;
    arr="hello world";
    char *a=gets(str);//gets()返回的是首地址
    printf("%p\n",a);
    printf("%p\n",a+1);
    puts(arr);
    puts("chi\na");
    printf("%s\n",arr);
    printf("%s\n",str);
    system("pause");
}
#--------运行结果---------
hhh
000000000061FE06
000000000061FE07
hello world
chi
a
hello world
hhh

通过字符数组名或者字符指针变量可以输出一整个字符串,因为他会自动将地址加1进行输出,但数组则不行,需要逐个输出
字符串赋值给指针变量也是相当于数组,将首地址赋值给指针,因为指针变量只能用来存储地址,这点是很重要的

使用字符指针变量与字符数组的区别

  1. 字符数组由若干元素组成,每个元素放一个字符,而字符指针变量中存放的是地址
  2. 可以对字符指针变量赋值,但不可以对数组名赋值,比如上面对指针变量的赋值
char str[10];
str[0]="j"; //合法
str="hello world"; //非法,因为数组名的本质是一个地址,不能被赋值
  1. 编译时为字符数组分配若干存储单元,以存放各元素的值,而对字符指针变量,只分配一个存储单元
//所以该写法是危险的
char *a;
scanf("%s",a);

因为在编译时a已经分配了存储单元,但a中的存储单元是一个不确定的值,可能指向内存中的未知区域,现在就相当于向该未知区域输入字符串,可能破坏系统造成严重后果,所以要避免这种写法

  1. 指针变量的值是可以改变的,因为其存放的是地址,加1就代表指向下一个字符的地址;而字符数组名代表的是一个固定的值,即数组元素的首地址,所以是不能改变的
  2. 字符数组的元素是可以改变的,但字符指针变量指向的字符串常量内容则不可以改变
char a[]="hello";
char *b="hello";
a[2]='r';//可以改变
b[2]='r';//不可以改变
  1. 可以用指针变量或者字符数组代替printf()中的格式字符串
char *format;
format="a=%d,b=%d";
printf(format,a,b);
//相当于printf("a=%d,b=%d",a,b);
//同理字符数组也能实现
<think>好的,我现在要仔细分析用户的问题,关于C语言字符指针字符数组的区别及使用场景。首先,用户引用了多个资料,需要结合这些资料来组织答案。用户可能已经有一定的C语言基础,但可能对指针数组的具体区别不太清楚,尤其是在字符处理方面容易混淆。 首先,我需要回顾字符指针字符数组的基本定义。根据引用[2],字符指针是指向字符类型的指针,例如`const char* pc = "abcdef";`,这里的pc存储的是字符串首字符的地址。而字符数组则是存储字符数组,例如`char arr[] = "abcdef";`,这时候数组arr在内存中拥有整个字符串的副本,每个字符都是数组的一个元素。 接下来,区别方面需要从内存分配、修改权限、赋值方式、sizeof结果等方面展开。比如,字符数组在定义时分配足够的内存,可以修改内容,而字符指针指向的字符串字面量可能存储在只读区域,不可修改。这一点在引用[2]中提到过,当用指针存储字符串时,存储的是首字符地址,整个字符串可能不可修改。 然后,使用场景需要分别说明。字符数组适合需要修改字符串内容的情况,比如缓冲区操作。而字符指针常用于指向字符串字面量或动态分配内存,适合作为函数参数传递,或者处理只读字符串的情况。引用[4]也提到,很多操作通过指针实现,所以指针在处理动态内存或字符串传递时更灵活。 还要注意常见错误,比如字符指针未初始化就使用,或者试图修改字符串字面量的内容导致崩溃。引用[5]中的例子说明指针的解引用操作,需要正确理解指针的层级关系,避免错误。 需要确保回答结构清晰,分点列出区别使用场景,并给出示例代码。同时,生成的相关问题要围绕用户可能的后续疑问,比如初始化方式、内存管理、常见错误等。 最后,检查是否符合格式要求,行内公式用$...$,独立公式用$$...$$,虽然当前问题可能不涉及数学公式,但如果有需要的地方要正确应用。引用标识要自然添加在对应的知识点后面,确保引用来源准确。</think>### 字符指针字符数组的区别及使用场景 #### 一、核心区别 1. **内存分配方式** - **字符数组**:在声明时分配固定内存空间,存储字符串的完整副本。例如: $$char\ a[] = "hello";$$ 此时数组$a$占6字节(含结尾的$\text{\\0}$),内存由编译器自动分配[^2][^4]。 - **字符指针**:仅存储字符串首字符的地址,指向的字符串可能位于只读区域(如字符串字面量)。例如: $$char\ *p = "hello";$$ 指针$p$本身占用4/8字节(取决于系统),但字符串内容不可修改[^5]。 2. **修改权限** - 字符数组内容可修改(如$a[0] = 'H'$),而字符指针指向的字符串字面量通常不可修改(尝试修改会导致未定义行为)[^2][^4]。 3. **赋值方式** - 字符数组只能在初始化时整体赋值,后续需逐个元素修改;字符指针可重新指向其他字符串地址。例如: ```c char arr[10]; arr = "new"; // 错误!数组名是常量指针 char *p = "old"; p = "new"; // 合法,p指向新的字符串地址 ``` 4. **sizeof结果** - `sizeof(数组名)`返回数组总字节数,`sizeof(指针)`返回指针变量的大小(如4字节)[^3]。 --- #### 二、使用场景对比 | **场景** | **字符数组** | **字符指针** | |------------------------|----------------------------------------|---------------------------------------| | 需要修改字符串内容 | ✅ 直接操作数组元素 | ❌ 若指向字符串字面量则不可修改 | | 动态内存管理 | ❌ 固定大小,无法动态扩展 | ✅ 可指向动态分配的内存(如malloc) | | 函数参数传递 | 传递数组首地址(退化为指针) | 直接传递指针,灵活性更高 | | 存储只读字符串 | ❌ 浪费内存(需完整拷贝) | ✅ 节省内存,仅存储地址 | --- #### 三、代码示例 1. **字符数组的修改** ```c char arr[] = "hello"; arr[0] = 'H'; // 合法,数组内容变为"Hello" ``` 2. **字符指针的只读性** ```c char *p = "world"; p[0] = 'W'; // 运行时错误!尝试修改只读内存 ``` 3. **动态内存分配(指针优势)** ```c char *p = malloc(10 * sizeof(char)); strcpy(p, "dynamic"); free(p); // 使用后需手动释放内存 ``` --- #### 四、常见错误 1. **未初始化的指针** ```c char *p; strcpy(p, "test"); // 野指针,导致崩溃 ``` 2. **混淆指针数组的赋值** ```c char arr[6]; arr = "hello"; // 错误!数组名不可重新赋值 ``` 3. **越界访问** ```c char *p = "short"; printf("%c", p[10]); // 访问非法内存 ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值