C语言字符数组与字符指针分析

1 字符数组

字符数组的表示方式:

#include <stdio.h>
#include <string.h>

int main()
{
    int i;
    char str[] = "string int pointer";
    int len = strlen(str);

    // 直接输出
    printf("%s\n", str);

    // 字符拼接输出
    for (i = 0; i < len; i++)
    {
        printf("%c", str[i]);
    }

    printf("\n");

    return 0;
}

运行结果

 2 字符指针

字符指针的表示方式:

#include <stdio.h>
#include <string.h>

int main()
{
    int i;
    char str[] = "string int pointer";
    char *ptr = str;
    int len = strlen(str);

    // 直接输出
    printf("%s\n", ptr);

    // 使用*(ptr + i)输出
    for (i = 0; i < len; i++)
    {
        printf("%c", *(ptr + i));
    }

    printf("\n");

    // 使用ptr[i]输出
    for (i = 0; i < len; i++)
    {
        printf("%c", ptr[i]);
    }

    printf("\n");

    // 使用*(str + i)
    for (i = 0; i < len; i++)
    {
        printf("%c", *(str + i));
    }

    printf("\n");

    return 0;
}

 运行结果

 3 字符数组、字符指针和整型指针的区别分析

3.1 字符指针和整型指针的区别

#include <stdio.h>

int main()
{
    // 字符指针
    char *str = "hello world";
    printf("str = %s\n", str); //字符指针指向的字符串内容
    printf("*str = %c\n", *str); //字符串的首个字符内容
    printf("str = %p\n", str); //字符指针指向的地址
    printf("&str = %p\n", &str); //字符指针本身的地址

    // 整型指针
    int a = 10;
    int *ptr = &a;
    printf("&a = %p\n", &a); //a的地址
    printf("ptr = %p\n", ptr); //ptr指向的地址
    printf("*ptr = %d\n", *ptr); //ptr指向的内容
    printf("&ptr = %p\n", &ptr); //ptr的地址

    return 0;
}

运行结果:

str = hello world //字符指针指向的字符串内容
*str = h //字符串的首个字符内容
str = 0000000000404000 //字符指针指向的地址
&str = 000000000061FE18 //字符指针本身的地址
&a = 000000000061FE14 //a的地址
ptr = 000000000061FE14 //ptr指向的地址
*ptr = 10 //ptr指向的内容
&ptr = 000000000061FE08 //ptr的地址

整型指针:*就是取值,*ptr就是将ptr所指向的值取出,而ptr则是指针指向的地址,&ptr则是指针的地址。

字符指针:*str是输出字符串中的第一个字符,而str却输出了整个字符串,也可以表示字符指针指向的地址,&str则是表示字符指针本身的地址。

注:字符指针是唯一一种可以直接指向结果的类型,如char *str = "hello world",而其他类型不可以,比如整型指针:int *a = 10,这是一种错误写法。

3.2 字符指针和字符数组的区别

#include <stdio.h>
int main()
{ 
    // 字符指针
    char *str = "hello world";
    printf("str = %s\n", str); //字符指针指向的字符串内容
    printf("*str = %c\n", *str); //字符串的首个字符内容
    printf("str = %p\n", str); //字符指针指向的地址
    printf("&str = %p\n", &str); //字符指针本身的地址
    printf("字符常量的地址 = %p\n", "hello world");

    printf("============================\n");

    // 字符数组
    char array[] = "c-language";
    printf("字符数组的内容: array = %s\n", array);
    printf("字符数组的地址: array = %p\n", array);
    printf("字符数组的地址: &array = %p\n", &array);
    printf("字符常量的地址: %p\n", "c-language");

    return 0;
}

运行结果:

str = hello world
*str = h
str = 0000000000404000
&str = 000000000061FE18
字符常量的地址 = 0000000000404000
============================
字符数组的内容: array = c-language
字符数组的地址: array = 000000000061FE0D
字符数组的地址: &array = 000000000061FE0D
字符常量的地址: 00000000004040E4

相同点:字符指针和字符数组都可以使用%s输出整个字符串,都可以使用*或者[ ]获取单个字符。

不同点:字符数组存储在全局数据区或栈区,字符指针的字符串存储在常量区。全局数据区和栈区的字符串有读取和写入的权限,而常量区的字符串只有读取的权限,没有写入的权限。

内存权限的不同导致的一个明显结果就是,字符数组在定义后可以读取和修改每个字符,而对于字符指针形式的字符串,一旦被定义后就只能读取不能修改,任何对它的赋值都是错误的。

 字符数组修改字符:

#include <stdio.h>

int main()
{
    char str[] = "hello world";
    printf("str = %s\n", str); // str = hello world

    str[0] = 'H';
    str[1] = 'E';
    str[2] = 'L';

    printf("str = %s\n", str); // str = HELlo world

    return 0;
}

字符指针无法修改字符:

#include <stdio.h>

int main()
{
    char *str = "hello world";
    printf("%s\n", str); // hello world

    str = "nihao shijie"; //正确
    printf("%s\n",str); // nihao shijie

    str[0] = 'H'; //错误 Segmentation fault

    return 0;
}

4 总结

字符数组:

char str[] = "hello world";

字符指针:

char *str = "hello world";

 4.1 存储方式

1)字符数组是由若干元素组成,每个元素存放一个字符;

2)字符指针只存放字符串的首地址,不是整个字符串。

 4.2 存储位置

1)字符数组实在内存中开辟了一段空间存放字符串;

2)字符指针是在文字常量区开辟了一段空间存放字符串,将字符串的首地址给了字符指针变量。

 4.3 是否可被修改

1)指针变量指向的字符串的内容是不能被修改,但是字符指针变量(即存放的地址或指向)是可以被修改;

2)字符数组的内容可以被修改,单字符数组名所代表的字符串首地址不能被修改。

4.4 初始化

定义一个数组,在编译时就为它分配了内存单元,它是有确定的地址;而定义一个字符指针变量时,一定要将其初始化,否则指针变量的值会指向不确定的内存段,将会破坏程序。

char str[10]; // 可以

// 可以
char *p = NULL;
p = (char *)malloc(10);

// 不可以
char *p;

在后期的编程过程中,凡是涉及到对字符串的读取,都可以使用字符数组和字符指针都能够满足需求;一旦是要写入或者修改某个字符,那么只能使用字符数组来表示字符串。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值