2024年C C++最新深入 char ,char ,char a[ ] ,char a[] 内核_char 65(2),2024年C C++工作或更难找

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

可以看到 s = 0x00422020 ,这也是"China"的首地址

所以,printf(“%s”,0x00422020);也是等效的。。

字符数组:

char  str[10] = “hello”;

前面已经说了,str = &str[0] , 也等于 "hello"的首地址。。

所以printf(“%s”,str); 本质也是 printf(“%s”, 地址");

C语言中操作字符串是通过它在内存中的存储单元的首地址进行的,这是字符串的终极本质。。。

5  char *  与 char  a[ ];

char  *s;

char  a[ ] ;

前面说到 a代表字符串的首地址,而s 这个指针也保存字符串的地址(其实首地址),即第一个字符的地址,这个地址单元中的数据是一个字符,

这也与 s 所指向的 char 一致。

因此可以 s = a;

但是不能 a = s;

C语言中数组名可以复制给指针表示地址, 但是却不能赋给给数组名,它是一个常量类型,所以不能修改。。

当然也可以这样:

    char  a [ ] = "hello";
    char *s =a;
    for(int i= 0; i < strlen(a) ; i++)
          printf("%c", s[i]);
    或  printf("%c",*s++);

字符指针可以用 间接操作符 *取其内容,也可以用数组的下标形式 [ ],数组名也可以用 *操作,因为它本身表示一个地址 。。

比如 printf(“%c”,*a);  将会打印出 ‘h’

char * 与 char a[ ] 的本质区别:

当定义 char a[10 ]  时,编译器会给数组分配十个单元,每个单元的数据类型为字符。。

而定义 char *s 时,  这是个指针变量,只占四个字节,32位,用来保存一个地址。。

sizeof(a) = 10 ;

sizeof(s)  = ?

当然是4了,编译器分配4个字节32位的空间,这个空间中将要保存地址。。。

printf(“%p”,s);

这个表示 s 的单元中所保存的地址。。

printf(“%p”,&s);

这个表示变量本身所在内存单元地址。。。。,不要搞混了。。

用一句话来概括,就是 char *s 只是一个保存字符串首地址的指针变量, char a[ ] 是许多连续的内存单元,单元中的元素为char ,之所以用 char *能达到

char a  [ ] 的效果,还是字符串的本质,地址,即给你一个字符串地址,便可以随心所欲的操所他。。但是,char* 和 char a[ ] 的本质属性是不一样的。。

6      char **  与char  * a[ ] ;

先看 char  *a [ ] ;

由于[ ] 的优先级高于* 所以a先和 [ ]结合,他还是一个数组,数组中的元素才是char * ,前面讲到char * 是一个变量,保存的地址。。

所以 char *a[ ] = {“China”,“French”,“America”,“German”};

同过这句可以看到, 数组中的元素是字符串,那么sizeof(a) 是多少呢,有人会想到是五个单词的占内存中的全部字节数 6+7+8+7 = 28;

但是其实sizeof(a) = 16;

为什么,前面已经说到, 字符串常量的本质是地址,a 数组中的元素为char * 指针,指针变量占四个字节,那么四个元素就是16个字节了

看一下实例:

    #include <stdio.h>
   int main()
   {
    char *a [ ] = {"China","French","America","German"};
    printf("%p %p %p %p\n",a[0],a[1],a[2],a[3]);
    return 0;
   }

可以看到数组中的四个元素保存了四个内存地址,这四个地址中就代表了四个字符串的首地址,而不是字符串本身。。。

因此sizeof(a)当然是16了。。

注意这四个地址是不连续的,它是编译器为**“China”,“French”,“America”,“German” 分配的内存空间的地址, 所以,四个地址没有关联。**

    #include <stdio.h>
   int main()
   {
   char *a [ ] = {"China","French","America","German"};
           printf("%p %p %p %p\n",a[0],a[1],a[2],a[3]); //数组元素中保存的地址
   printf("%p %p %p %p\n",&a[0],&a[1],&a[2],&a[3]);//数组元素单元本身的地址
   return 0;
   }

可以看到 0012FF38 0012FF3C 0012FF40 0012FF44,这四个是元素单元所在的地址,每个地址相差四个字节,这是由于每个元素是一个指针变量占四个字节。。。

char **s;

char **为二级指针, s保存一级指针 char *的地址,关于二级指针就在这里不详细讨论了 ,简单的说一下二级指针的易错点。

举例:

   char *a [ ] = {"China","French","America","German"};
   char **s =   a;

为什么能把 a赋给s,因为数组名a代表数组元素内存单元的首地址,即 a = &a[0] = 0012FF38;

而 0x12FF38即 a[0]中保存的又是 00422FB8 ,这个地址, 00422FB8为字符串"China"的首地址。

即 *s = 00422FB8 = “China”;

这样便可以通过s 操作 a 中的数据

      printf("%s",*s);
      printf("%s",a[0]);
      printf("%s",*a);

都是一样的。。。

但还是要注意,不能a = s,前面已经说到,a 是一个常量。。

再看一个易错的点:

  char **s = "hello world";

这样是错误的,

因为  s 的类型是 char **  而 "hello world "的类型是 char *

虽然都是地址, 但是指向的类型不一样,因此,不能这样用。,从其本质来分析,“hello world”,代表一个地址,比如0x003001,这个地址中的内容是 ‘h’

,为 char 型,而 s 也保存一个地址 ,这个地址中的内容(*s) 是char * ,是一个指针类型, 所以两者类型是不一样的。 。。

如果是这样呢?

   char  **s;
   *s = "hello world";

貌似是合理的,编译也没有问题,但是 printf(“%s”,*s),就会崩溃

why??

咱来慢慢推敲一下。。

printf(“%s”,*s); 时,首先得有s 保存的地址,再在这个地址中找到 char *  的地址,即*s;

举例:

   s = 0x1000;

在0x1000所在的内存单元中保存了"hello world"的地址 0x003001 , *s = 0x003001;

这样printf(“%s”,*s);

这样会先找到 0x1000,然后找到0x003001;

如果直接 char  **s;

   *s = "hello world";

s 变量中保存的是一个无效随机不可用的地址, 谁也不知道它指向哪里。。。。,*s 操作会崩溃。。

所以用 char **s 时,要给它分配一个内存地址。

   char  **s ;
   s = (char **) malloc(sizeof(char**));
   *s =  "hello world";

这样 s 给分配了了一个可用的地址,比如 s = 0x412f;

然后在 0x412f所在的内存中的位置,保存 "hello world"的值。。

再如:

   #include  <stdio.h>
   void  buf( char **s)
    {
           *s = "message";
    }
    int main()
    {
        char *s ;
        buf(&s);
        printf("%s\n",s);
    }

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

*s ;
buf(&s);
printf(“%s\n”,s);
}


  


[外链图片转存中...(img-0tqQV9In-1715564540861)]
[外链图片转存中...(img-Me9PfOaP-1715564540861)]

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 16
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值