char str[5] = {‘a‘,‘b‘,‘c‘,‘d‘,‘\0‘};
char str1[] = {"jack"}; // 只有直接给字符串数组初始化为一个串的时候,才会自动追加\0,前提还要是字符数组长度足够
char str2[] = "jack";
char* str = "jack";
printf("看看使用指针字符能否打印出来字符串:%s\n",str);
内存中分为五块区域
栈
(是专门用来存储局部变量的,所有的局部变量都是声明在栈区域的)
堆
(它运行程序员手动的从堆 申请空间来使用,程序员自己申请指定字节数的空间就从堆中申请)
BSS 段
(是用来存储未初始化的全局变量和静态变量的,声明一个全局变量,如果我们没有初始化,在程序运行的最开始时候,这个全局变量是没有初始化的,运行起来以后才会给他初始化,这也需要个过程)
数据段/常量区
(用来存储已经初始化的全局变量和静态变量,还有常量数据,10,20 等)
代码段
(用来存储程序的代码/指令)
为什么要分为五个区域,每个与区是干嘛的?
// 局部变量
int main(){
char str[] = "jack"; // 字符数组
char* pstr = "jack"; // 字符指针
}
字符指针的方式:pstr 是一个局部变量,这个指针变量是声明在栈区的,这个时候,字符串数据是存储在常量区的,字符串数据是以字符数组的形式存储在常量区
pstr 指针变量中存储的是"jack"这个字符串在常量区的地址
char str[] = "jack"; // 字符数组
char* pstr = "rose"; // 字符指针
printf("str[]的内存地址:%p\n",str);
printf("pstr 的内存地址:%p\n",pstr);
// 输出结果:可以看到这两个地址相差的很远,可以说明他们根本不在一个区域
str[]的内存地址:0x7ffeefbff44b
pstr 的内存地址:0x100000f17
// 全局变量
char str[] = "jack"; // 字符数组
char* pstr = "jack"; // 字符指针
这两种方式的区别
以字符数组存储:无论如何是一个字符数组,然后字符串的每一个字符存储在数组的元素之中的
以字符串指针存储:无论如何首先有一个字符指针变量,字符串数据是以字符数组的形式存储在常量区的
大前提:以字符指针形式存储的字符串
如果有:才会将这个字符数组直接返回地址
如果没有,才会将这个字符串数据存储在常量区,再返回地址
// 字符串的恒定性
char* name1 = "jack";
char* name2 = "jack";
char* name3 = "jack";
printf("name1的内存地址:%p\n",name1);
printf("name2的内存地址:%p\n",name2);
printf("name3的内存地址:%p\n",name3);
// 打印的结果:
name1的内存地址:0x100000f02
name2的内存地址:0x100000f02
name3的内存地址:0x100000f02
// 最容易蒙圈的地方
char* name4 = "rose";
name4 = "新修改的值"; // 字符串可以重新进行赋值,直接将字符串赋值给字符指针就可以,这样就是在常量区新创建一个一个字符串,name4 字符指针直接指向了该新创建的字符串地址
char name5[] = "hhhhh";
// name5 = "wwwww"; // 这样写是不行的,name5 是一个字符数组,name5 代表是数组的第 0 个元素的地址,所以不能直接将字符串赋值给地址,只能通过下标修改.
char str[][10] = {
"jack",
"rose",
"shanshan",
"wahaha"
};
for (int i = 0; i < 4; i++) {
printf("数组的数据是:%s\n",str[i]);
}
char* name[4] = {
"jack",
"rose",
"lili",
"xiaoru"
}; // 这是一个字符指针的一维数组,每一个数组的元素是一个字符指针,但是字符指针又不限定字符串的长度
for (int i = 0; i < 4; i++) {
printf("字符数组的每个元素的值是:%s\n",name[i]);
}
// fputs()函数
// 输出到标准输出流,控制台
char* name = "jack";
fputs(name,stdout);// 要输出的字符串,输出的地方(stdout 标准输出流)
// 将字符串存储到文件中
// 1,要声明一个文件指针,这个文件指针指向磁盘上的文件
// fopen(文件的路径,操作文件的模式)
// "w",write 写入
// "r",读的模式
// "a",追加模式
// fouts(要写入的字符串,文件指针)
FILE* pfile = fopen("/Users/mac/Desktop/c语言学习/C语言学习库/指针/a.txt", "w");
char* name1 = "我要好好学习 oc语言";
fputs(name1, pfile);
// 当操作模式是"w",文件不存在就会创建一个,如果文件存在就会将源文件替换掉
// 当操作模式是"a",文件存在则追加在文件末尾,文件不存在就会创建这个文件
// fgets()函数从控制台读取
/*
char name[10]; // 定义一个数组
printf("请输入:\n");
fgets(name, 10, stdin); // 长度与数组长度一致的,超过会报错
// 为什么说是安全的
// 如果输入的输入的字符串长度大于等于了第二个参数,那么就会取 n-1 个,最后一个为\0,这样就不会崩溃了,所以说是安全的
printf("您输入的是:%s\n",name);
printf("----华丽的分割线----\n");
unsigned long len = strlen(name);
printf("len = %lu\n",len);
// for (int i = 0; i< len; i++) {
// if(name[i] == ‘\n‘){
// name[i] = ‘\0‘;
// }
// }
// printf("您输入的是:%s\n",name);
// printf("现在的len = %lu\n",len);
// 这样循环不咋好,太浪费性能,我只需要知道最后一个值是不是\n,就行了,所以不用 for 循环
if(name[len-1] == ‘\n‘){
name[len-1] = ‘\0‘;
};
printf("您输入的是:%s\n",name); // 这样将\n 替换成了\0,但是字符串的长度还是没有变的哦
printf("现在的len = %lu\n",len);
注意:
使用 fgets 函数从文件流中读取数据,就是从磁盘上文件的内容
// fgets 从文件h中读取
FILE* file = fopen("/Users/mac/Desktop/c语言学习/lianxi.txt", "r");
char fname[10];
fgets(fname, 10, file);
// char* fname;// 使用字符指针是不行的哦,指针是存储的地址
// fgets(fname, 10, file);
printf("从文件中读取的内容是:%s\n",fname);
原文:https://www.cnblogs.com/shanshan-test/p/13096353.html