一、字符串和字符串IO
-
字符串是以空字符(\0)结尾的char类型数组
-
puts()函数只显示字符串,自动在显示的末尾加上换行符
#include <stdio.h>
#define MSG "I am a symbolic string constant"
#define MAXLENGTH 81
int main(void){
char words[MAXLENGTH] = "I am a sting in an array.";
const char *pt1 = "Something is pointing at me";
puts(MSG);
puts(words);
puts(pt1);//可以看到将pt1的指针直接放进puts函数里面就可以打印完整的字符串
words[8]='p';
puts(words);
return 0;
}
运行结果//可以看到puts()函数自己在末尾加了换行符
I am a symbolic string constant
I am a sting in an array.
Something is pointing at me
I am a sping in an array.
进程已结束,退出代码0
二、字符串字面量
- 用双引号括起来的内容叫字符串字面量也叫字符串常量
- 编译器会在字符串的末尾自动加入\0字符
- 字符串常量属于静态存储类别,在函数中使用的字符串常量只存储一次,在整个程序的生命周期存在,即使函数被调用多次
- 用双引号括起来的内容被视为指向该字符串存储位置的指针
#include <stdio.h>
int main(void){
printf("%s,%p,%c\n","We","are",*"space farers");//*"space farers"表示该字符串首字符的地址
return 0;
}
运行结果
We,0x100027fa5,s
进程已结束,退出代码0
三、字符串数组的初始化
-
用指定的字符串初始m1,const 表明不会更改这个字符串
const char m1[40]="Limit yourself to one line's worth"
-
没有空字符,就不是一个字符串,而是一个字符数组
const char m1[40] ={'L','i','m','i','t'}//这里面没有空字符,所以它是一个字符数组而不是字符串
-
可以让编译器确定数组的大小
const char m2[] ="if you can't think of anything"
-
字符数组名和其他数组名一样,是该数组元素的首地址
char car[10] ="Tata" -------------------------------------------------- car =&car[0]、*car == 'T' 、*(car+1) ==car[1] =='a'
-
可以使用指针法创建数组(下面两者定义方式几乎相同)
const char *pt1 ="Somthing is point at me" const char ar1[] ="Somthing is point at me"
四、数组和指针的差异
-
相同点
- 数组和指针都会在末尾加上一个空字符
-
不同点
-
初始化数组是把静态存储区的字符串拷贝到数组中,而初始化指针只是把字符串的地址拷贝给指针
-
以上面ar1为例,ar1是数组元素的首地址,可以进行ar1+1的操作,但是不能进行++ar1的操作,递增运算符只能用于变量名前,不能用于常量。而指针形式(*pt1)可以
-
编译器会为指针变量pt1留出一个存储位置
#include <stdio.h> #define MSG "I'm special" int main(void){ char ar[] =MSG; const char *pt = MSG; printf("address of \"I'm special \":%p \n","I'm special"); printf(" address ar:%p\n",ar); printf(" address pt:%p\n",pt); printf(" address of MSG %p\n",MSG); printf("address of \"I'm special \":%p\n","I'm special"); return 0; } //这里可以侧面印证是字符串常量,只有一份地址的值,而指针给它分配了不同的地址值 address of "I'm special ":0x1025a7f14 address ar:0x16d85af08 address pt:0x1025a7f14 address of MSG 0x1025a7f14 address of "I'm special ":0x1025a7f14 进程已结束,退出代码0
-
-
编译器可以用相同的地址替换每个”Klingon“实例,,如果允许p1[0]修改'F',将影响所有使用该字符串的代码。如果打算修改字符串,就不要用指针指向字符串字面量(可以看出下图报错了)
五、字符串数组
- mytalents数组内含5个指针的数组,共占用40个字节,yourtalents是一个内含5个数组的数组,每个数组内含40个char类型的值,共占200字节
- mytalents指向初始化时所用的字符串字面量的位置,这些字符串被存在静态内存中,而yourtalents中的数组则存储着字符串字面量的副本,每个字符串都被存储了两次。
- mytalents数组的指针元素所指向的字符串不必存储在连续的内存中
- yourtalents中的每个元素的大小必须相同,而且必须是能存储最长字符串的大小
#include <stdio.h>
#define SLEN 40
#define LIM 5
int main(void){
const char *mytalents[LIM] ={
"Adding numbers swifty",
"Multiplying accurate","Stashing data",
"Following instructions to the letter",
"Understanding the C language"
};
char yourtalents[LIM][SLEN] ={
"Walking in straight line",
"Sleeping","Watching television",
"Mailing letters","Reading email"
};
int i;
puts("Let's compare talents.");
printf("%-36s %-25s\n","My Talents","your Talents");
for(i=0;i<LIM;i++)
printf("%-36s %-25s\n",mytalents[i],yourtalents[i]);
printf("\nsizeof mytalents:%zd,sizeof yourtalents: %zd\n",sizeof(mytalents),sizeof(yourtalents));
return 0;
}
运行结果
Let's compare talents.
My Talents your Talents
Adding numbers swifty Walking in straight line
Multiplying accurate Sleeping
Stashing data Watching television
Following instructions to the letter Mailing letters
Understanding the C language Reading email
sizeof mytalents:40,sizeof yourtalents: 200
七、指针和字符串
- 程序并未拷贝字符串,语句copy=mesg;把mesg的值赋值给copy,即让copy也指向mesg的字符串
#include <stdio.h>
int main(void){
const char *mesg ="Don't be a fool";
const char *copy;
copy = mesg;
printf("%s\n",copy);
printf("mesg =%s;&mesg =%p;value =%p\n",mesg,&mesg,mesg);
printf("copy =%s;© =%p;value =%p\n",copy,©,copy);
return 0;
}
运行结果
Don't be a fool
mesg =Don't be a fool;&mesg =0x16ce1af10;value =0x102fe7f68
copy =Don't be a fool;© =0x16ce1af08;value =0x102fe7f68
进程已结束,退出代码0
标签:const,char,数组,字符串,copy,mesg
From: https://www.cnblogs.com/sunhuaiguo/p/17524407.html