Skip to main content

25.一节课讲明白c语言指针(中③)

       hello,小伙伴们,大家好,这里是左左右,这期视频接着给大家讲C语言基础中指针这一部分,首先我来写一段大家熟悉的代码,这时使用%s就可以将完整的字符串打印出来了。

test.c
#include<stdio.h>

int main()
{
char arr1[] = "hello vscode";
char *p1 = arr1;
printf("%s\n%s\n",p1,arr1);

return 0;
}

Docusaurus logo        我们返回来看一下这段代码,那么这两行代码是不是可以合并为一行呢,答案是可以的,打印输出,是不是结果和之前是一样的?

test.c
#include<stdio.h>

int main()
{
char arr1[] = "hello vscode";
char *p1 = arr1;
printf("%s\n%s\n",p1,arr1);

char *p2 = "hello vscode";
printf("%s\n",p2);

return 0;
}

Docusaurus logo        接着我们返回来看一下这行代码,它的等号一边是指针,而另一边是字符串,两边怎么会等效呢?其实c语言内部在运行到这行代码时,默认指针仍然存放的是字符串中第一个元素的首地址,我们打印输出来验证一下我的说法,这时输出的结果是不是就是数组中的第一个元素?

test.c
#include<stdio.h>

int main()
{
char arr1[] = "hello vscode";
char *p1 = arr1;
printf("%s\n%s\n",p1,arr1);

char *p2 = "hello vscode";
// printf("%s\n",p2);
printf("%c\n%c\n",*p2,p2[0]);

return 0;
}

Docusaurus logo        这时有的小伙伴就要问了,第二种写法比第一种明显要简单明了,那么我们以后能不能就按第二种写法来写呢,答案是不可以的,他两还是有区别的,这时假设我们要将字符串arr1中的第一个元素改为f,这时打印输出是不是也没有问题?

test.c
#include<stdio.h>

int main()
{
char arr1[] = "hello vscode";
arr1[0] = 'f';
char *p1 = arr1;
printf("%s\n%s\n",p1,arr1);

char *p2 = "hello vscode";
// printf("%s\n",p2);
printf("%c\n%c\n",*p2,p2[0]);

return 0;
}

Docusaurus logo        我们要将第二种写法中的第一个元素改为f,这时打印输出是不是就出问题了?这是因为第二种写法c语言默认会将字符串放到内存的只读区域,也就是说这时的字符串hello vscode它是只读的,是不允许被更改的,为了防止被更改,我们可以在前面加一个const 的关键词,这个关键词的作用就是用来声明对象是不可以被修改,这时我们打印输出是不是有报错提示了?

test.c
#include<stdio.h>

int main()
{
char arr1[] = "hello vscode";
arr1[0] = 'f';
char *p1 = arr1;
printf("%s\n%s\n",p1,arr1);

const char *p2 = "hello vscode";
p2[0] = 'f';
// printf("%s\n",p2);
printf("%c\n%c\n",*p2,p2[0]);

return 0;
}

Docusaurus logo        我们接着再讲结构体那一期视频时挖了一个指针的坑,现在我们就把之前挖的坑给填上,我们返回来看当时的那段代码是不是就明白我为什么要定义成指针类型的了?那么我们把这里的指针定义成字符串类型的可以吗?当然是可以的,点击运行发现报错了,这是因为数组名是不可以直接赋值的。

test.c
#include<stdio.h>
typedef struct{
int id;
char name[10];
int age;
}Student;
int main()
{
Student st1;
st1.id = 2025001;
st1.name = "高启强";
st1.age = 17;
printf("学生1的学号是:%d,学生1的姓名是:%s,学生1的年龄是:%d",st1.id,st1.name,st1.age);

// char arr1[] = "hello vscode";
// arr1[0] = 'f';
// char *p1 = arr1;
// printf("%s\n%s\n",p1,arr1);

// const char *p2 = "hello vscode";
// // p2[0] = 'f';
// // printf("%s\n",p2);
// printf("%c\n%c\n",*p2,p2[0]);

return 0;
}

Docusaurus logo        我们回到刚才的代码给数组名直接赋值,是不是报了相同的错误?

test.c
#include<stdio.h>
typedef struct{
int id;
char name[10];
int age;
}Student;
int main()
{
// Student st1;
// st1.id = 2025001;
// st1.name = "高启强";
// st1.age = 17;
// printf("学生1的学号是:%d,学生1的姓名是:%s,学生1的年龄是:%d",st1.id,st1.name,st1.age);

char arr1[] = "hello vscode";
// arr1[0] = 'f';
char *p1 = arr1;
arr1 = "hello vs";
printf("%s\n%s\n",p1,arr1);

// const char *p2 = "hello vscode";
// // p2[0] = 'f';
// // printf("%s\n",p2);
// printf("%c\n%c\n",*p2,p2[0]);

return 0;
}

Docusaurus logo        这时我们就要用到strcpy这个函数了,同时我们要将string.h的头文件引用过,点击运行是不是就没有问题了?

test.c
#include<stdio.h>
#include<string.h>
typedef struct{
int id;
char name[10];
int age;
}Student;
int main()
{
// Student st1;
// st1.id = 2025001;
// st1.name = "高启强";
// st1.age = 17;
// printf("学生1的学号是:%d,学生1的姓名是:%s,学生1的年龄是:%d",st1.id,st1.name,st1.age);

char arr1[] = "hello vscode";
// arr1[0] = 'f';
char *p1 = arr1;
strcpy(arr1,"hello vs");
printf("%s\n%s\n",p1,arr1);

// const char *p2 = "hello vscode";
// // p2[0] = 'f';
// // printf("%s\n",p2);
// printf("%c\n%c\n",*p2,p2[0]);

return 0;
}

Docusaurus logo        同理我们给结构体赋值,点击运行是不是也没有问题了?

test.c
#include<stdio.h>
#include<string.h>
typedef struct{
int id;
char name[10];
int age;
}Student;
int main()
{
Student st1;
st1.id = 2025001;
strcpy(st1.name,"高启强");
st1.age = 17;
printf("学生1的学号是:%d,学生1的姓名是:%s,学生1的年龄是:%d",st1.id,st1.name,st1.age);

// char arr1[] = "hello vscode";
// // arr1[0] = 'f';
// char *p1 = arr1;
// strcpy(arr1,"hello vs");
// printf("%s\n%s\n",p1,arr1);

// const char *p2 = "hello vscode";
// // p2[0] = 'f';
// // printf("%s\n",p2);
// printf("%c\n%c\n",*p2,p2[0]);

return 0;
}

Docusaurus logo        这时name中的字符串是可以更改的,这里我们将强哥改为左左右,打印输出是不是也没有问题,这时如果我们要输入的学生姓名是这样的呢(胡柏·布里恩·沃夫斯里积士丁可辛贝格多夫)?这时就超出定义字符串时向内存要的十字节的空间,这时点击运行,程序就出问题。

test.c
#include<stdio.h>
#include<string.h>
typedef struct{
int id;
char name[10];
int age;
}Student;
int main()
{
Student st1;
st1.id = 2025001;
strcpy(st1.name,"高启强");
// strcpy(st1.name,"左左右");
strcpy(st1.name,"胡柏·布里恩·沃夫斯里积士丁可辛贝格多夫");
st1.age = 17;
printf("学生1的学号是:%d,学生1的姓名是:%s,学生1的年龄是:%d",st1.id,st1.name,st1.age);

// char arr1[] = "hello vscode";
// // arr1[0] = 'f';
// char *p1 = arr1;
// strcpy(arr1,"hello vs");
// printf("%s\n%s\n",p1,arr1);

// const char *p2 = "hello vscode";
// // p2[0] = 'f';
// // printf("%s\n",p2);
// printf("%c\n%c\n",*p2,p2[0]);

return 0;
}.

Docusaurus logo        那我们将定义字符串时向内存要的空间多一点不就行了吗?但当我们输入短的字符串时,就造成大量空间的浪费,这时我们刚才指针的写法就凸显出它的优点了,不管名字长或短,输出都没有问题,也就是说指针的写法,内存空间是自动分配的,不用我们操心,这时我们将st1的姓名再改回强哥,调试输出是不是也没有问题。

test.c
#include<stdio.h>
#include<string.h>
typedef struct{
int id;
char *name;
int age;
}Student;
int main()
{
Student st1;
st1.id = 2025001;
// strcpy(st1.name,"高启强");
// strcpy(st1.name,"左左右");
st1.name = "胡柏·布里恩·沃夫斯里积士丁可辛贝格多夫";
st1.name = "高启强";
st1.age = 17;
printf("学生1的学号是:%d,学生1的姓名是:%s,学生1的年龄是:%d",st1.id,st1.name,st1.age);

// char arr1[] = "hello vscode";
// // arr1[0] = 'f';
// char *p1 = arr1;
// strcpy(arr1,"hello vs");
// printf("%s\n%s\n",p1,arr1);

// const char *p2 = "hello vscode";
// // p2[0] = 'f';
// // printf("%s\n",p2);
// printf("%c\n%c\n",*p2,p2[0]);

return 0;
}

Docusaurus logo        这时有的小伙伴就要疑惑了,刚才不是说数组名不是不能直接赋值吗?这里为什么没有报错,其实在结构体中我们定义的name它是一个指针,而非数组名,指针一开始指向的内存只读区中这一长串字符,后来指向的是强哥这个字符串,也就是说指针中储存的地址值发生变化了,指针本身就是一种变量,所以它里面的地址值是可以被重新赋值的。 Docusaurus logo        今天这期视频就解释了上期视频这个表格中最后一行的内容了。 Docusaurus logo        好的习题时间,大家可以通过弹幕的方式把答案发出来,同时我也会将答案放到评论区。

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

int main()
{
char arr1[] = "hello vscode";
char arr2[] = "hello vscode";
char *p1 = "hello vscode";
char *p2 = "hello vscode";
if(arr1 == arr2){
printf("哈哈\n");
}
if(p1 == p2){
printf("呵呵\n");
}
return 0;
}

答案:呵呵
原因:arr1和arr2指向的是内存中的不同地址,所以arr1≠arr2;
p1和p2指向的是内存只读区中的相同地址,所以p1=p2。
       这期视频如果听不懂的小伙伴们可以先前面三期视频听一遍,好的,今天的视频就到这里了,您的关注,点赞和收藏是我持续更新下去的最大动力,我们下期见。