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