char s[] 和 char* s 的区别

  • 1、数组本质
  • 2、指针
    • 指针的指向
  • 3、字符数组
  • 4、char * 与 char a[ ]
  • 5、char ** 和char *a[]
    • char *a[]
    • char ** s

C语言指针可以代替数组使用

1、数组本质

数组是多个元素的集合,在内存中分布在地址连续的单元中,因此可以通过其下标访问数组的不同数组。
例如:
下面展示一些

char s[3] = "0x1";
printf("s2字符串:\n");
printf("%c\n", s[0]);
printf("%c\n", s[1]);
printf("%c\n", s[2]);

2、指针

指针也是一种变量,只不过它的内存单元中保存的是一种标识其他位置的地址,而地址也是整数,在32位平台下,就是32位,4个字节(bytes)。

指针的指向

指针的指向是指 指针变量所保存的其他的地址单元中 所存放的数据类型。
例如:

int *ptr;//ptr指针保存的地址所在内存单元中的数据类型是整型
float *p;//这个p指针指向的内存地址存放的元素类型就是浮点型

而不管指向的数据类型是哪种,其实对于指针本身的值永远是整型,因为它保存的地址就是整数

3、字符数组

字符数组首先是数组,数组中的元素都是字符。

char s[10];//定义了一个含有10个元素的数组,元素类型为字符 %c

C语言中定义一个变量时,可以初始化,如下:

char s[10] = {"hello world"};

当编译器遇到上面的定义和赋值时,会将 hello world 和 \0 依次逐个填入连续数组内存中。

C语言中是没有真正的字符串类型,可以通过字符数组表示字符串,并且字符数组的元素地址也是连续的。C语言中规定数组代表数组所在内存位置的首地址,即 str字符串是等于str[0]的,str = &str[0];

对于printf("%s",str); 为什么用首地址就可以输出字符串?

因为对于C语言中字符串常量的本质就是一个地址,例如:

char  *s ;
s = "Hello";

这里把一个字符串赋值给一个字符串指针变量,起始就是C语言中编译器会给字符串常量分配地址,如果"Hello", 存储在内存中的 0x3000 0x3001 0x3002 0x3003 0x3004 0x3005 ,可以看出真正的意义就是
s = “Hello” = 0x3000
因此我们可以把Hello看做是字符串,而编译器会把他看做是地址 0x3000 ,即字符串常量的本质就是代表它的第一个字符的地址。

char *s;
s = "Hello";
printf("%p\n",s);//%p代表表示按十六进制输出数据,如果输出数据不够8位数,则左边补0


输出00796BD0,也就是"Hello"的首地址。

对于字符数组:

char str[10] = “Hello”;
也就是说str = &str[0]
C语言中操作字符串是通过它在内存中的存储单元的首地址进行的,这是字符串的终极本质。。。

4、char * 与 char a[ ]

对于char *s 与 char a[ ] :
a代表的是字符串的首地址,而s代表的这个指针保存字符串的首地址(第一个字符的地址),即可以看做: s =a ,即可以将数组名赋值给指针表示地址,但是 不能这样赋值 a = s ,即:不能将指针赋值给数组名
因为数组名是一个常量,是不可以修改的
可以通过如下方式访问数组元素:

char a[] = "Hello";
char*s = a;
int i;
for(i = 0;i < strlen(a);i++)
{printf("%c",s[i]);
//printf("%c",*s++);也可以
}

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

比如 printf("%c",*a); 将会打印出 ‘H’,

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

当定义char a[10]的时候,编译器会给数组分配10个单元,每个单元的数据类型都是字符,而定义char *s时,s是一个指针变量,只占4个字节,32位,用来保存一个地址。
sizeof(a) = 10,sizeof(s) = 4
a的长度是10,s的长度是4,因为s是一个int型

printf("%p",s)----------这个表示 s 的单元中所保存的地址。

printf("%p",&s);--------这个表示变量本身所在内存单元地址。。。。,不要搞混了。。

总结:char * s 只是一个保存字符串首地址的指针变量,char a[]是许多连续的内存单元,单元中的元素是char型,char * 和 char a[]具有相同的效果,源于字符串的本质,即给一个字符串地址,便可以操作字符串,但char* 和 char a[]的本质属性不一样。

5、char ** 和char *a[]

char *a[]

[]的优先级高于 * ,所以先是a[],它是一个数组,数组中的元素是char类型,char元素是一个变量,保存地址。
对于char *a[ ] = {“Dog”,“Cat”,“Chicken”};
数组中元素是字符串,sizeof(a)是12,并不是4+4+8,是因为字符串常量的本质是地址,a数组中元素是char *指针,指针变量是整数类型,占4个字节,则3个元素就是12个字节。

char *a[] = { "Dog","Cat","Chicken" };
printf("%p %p %p \n", a[0], a[1], a[2]);

可以看到数组中的三个元素保存了三个内存地址,这三个地址代表了三个字符串的首地址,而不是字符串本身,且三个地址不是连续的,它是编译器为"Dog",“Cat”,“Chicken” 分配的内存空间的地址,因此没有关联。

char *a[] = { "Dog","Cat","Chicken" };
printf("数组元素单元本身的地址:%p %p %p \n", &a[0], &a[1], &a[2]);//数组元素单元本身的地址


可以看到三个元素单元所在的地址是连续的,每个地址相差四个字节。

char ** s

char ** 为二级指针,s保存一级指针char *的地址,
例如:

char *a [ ] = { "Dog","Cat","Chicken" };
char **s =   a;//---有问题

数组a代表数组元素内存单元的首地址,,即a = &a[0] = 010FFD44,即 *s = 001D6BE0 = “Dog”,
这样可以通过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”,代表一个地址,比如0x000001,这个地址中的内容是 ‘H’,为char型,而s也保存一个地址,这个地址内容是char*,是一个指针类型。

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

编译没有问题,但是 printf("%s",s),就会崩溃, printf ("%s", s); 时,首先得有s 保存的地址,再在这个地址中找到 char * 的地址,即*s;

若s = 0x1000;
在0x1000所在的内存单元保存了“hello world”的地址0x000001,*s = 0x000001,这样printf("%s",*s)会先找到0x1000,然后找到0x000001,如果直接使用char **s,令 * s = “hello world”,s变量中保存的是一个无效随机不可用的值,不知道他指向哪里,所以用char **s时,要给他分配一个内存地址。

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

这样s给分配了一个可用的地址,s = 0x1234,然后再地址0x1234所在的内存中的位置,保存了“hello world”的值。

下列程序中,定义了字符指针s,s中存放了字符串"message"的地址。

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

即:二级指针保存的是一级指针的地址,它的类型就是指针变量,一级指针保存的是指向数据所在的内存单元的地址。

参考:
https://blog.csdn.net/daiyutage/article/details/8604720

C语言中 char s[] 和 char* s 的区别相关推荐

  1. C语言中,scanf与scanf_s的简单区别

    C语言中,scanf与scanf_s的简单区别 scanf()不会检查输入边界,可能造成数据溢出,scanf_s()会进行边界检查. 如name[5], scanf("%s",na ...

  2. java if和else if的区别_关于C语言中if,elseif和else的区别在哪里

    关于C语言中if,elseif和else的区别在哪里以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 关于C语言中if,e ...

  3. c+语言+null,C/C++语言中NULL、'\0’和0的区别

    NULL.'\0'和0的值是一样的,都是0,不过它们的表现形式不一样: 1. NULL: 即空指针,不过在C和C++中并不一样.在VS 2013的库文件string.h中可以看到如果定义. 1 /* ...

  4. C语言中,strlen()函数与sizeof()运算符的区别以及用法区别

    C语言编程中,会频繁地对数据进行操作. 其中为了防止内存的非法占用,判断数据的长度或者变量的大小是非常有必要的操作. 最常用的就是strlen()函数或者sizeof()运算符. 那么strlen() ...

  5. r语言中c函数错误,R语言中c()函数与paste()函数的区别说明

    c()函数:将括号中的元素连接起来,并不创建向量 paste()函数:连接括号中的元素 例如 c(1, 2:4),结果为1 2 3 4 paste(1, 2:4),结果为"1 2" ...

  6. c语言中static 函数和普通函数的区别?

    转自:https://bbs.csdn.net/topics/350238100 C程序一直由下列部分组成: 1)正文段--CPU执行的机器指令部分:一个程序只有一个副本:只读,防止程序由于意外事故而 ...

  7. c语言中的printf函数和scanf的区别

    --printf函数在c语言中的普通用法 在c语言中printf函数的作用非常大,用途也非常广泛,它主要具有打印功能. 在调用printf函数是必须给其提供格式串,格式串后面的参数是需要在显示时插入到 ...

  8. C语言中exit(0)与exit(1)的区别

    C语言中_exit(),exit(0)与exit(1)有什么区别 今天天气有点冷,当我在写消息队列的程序的时候,遇到了结束进程的这个问题,突然脑海里有点混乱,我是用_exit(),还是用exit(1) ...

  9. c语言中int类型与char类型数据转换

    1.char----->int: 少字节类型转换为多字节类型,没有影响,数据也不会发生变化. #include <stdio.h> int main() {char cret = 0 ...

  10. c语言中code table,unsigned char code table[]中的code的作用

    unsigned char code table[]中的code的作用是告诉单片机,我定义的无符号的字符串组放在ROM(程序存储区)里面,因为C语言中没办法详细描述存入的是ROM还是RAM(寄存器), ...

最新文章

  1. 使用VisualStudio2010连接CodePlex进行代码管理
  2. 醉没醉,带上智能手机走两步就知道
  3. 9月份准备备考RHCE 10份考试争取一次通过
  4. 学python的好处-python有什么优势
  5. 从局部脑到全脑:时空域分层神经网络脑电情绪识别模型
  6. (原创)C++11改进我们的程序之move和完美转发
  7. 她16岁因汶川地震改志学医,仅27岁当上浙大博导!她说:科研是“止不住想念到失眠的对象”...
  8. 百度-北大在Kaggle发起自动驾驶环境下的汽车6-DOF预测挑战赛
  9. VB案例:计算圆锥体积与面积
  10. 数据集_汇总 | SLAM、重建、语义相关数据集大全
  11. Python支持向量机(SVM)实例
  12. 【百度头条】精准微营销—本地离线92GBQQ群数据库,包含全部版本
  13. 新版edge浏览器没有internet选项怎么办?
  14. 在线LOGO的设计工具推荐
  15. 商务办公软件应用与实践【8】
  16. 任何人都有值得学习的地方,横瓜向[水牛党](4618415)请教问题
  17. Linux小白三天入门进阶笔记——DAY1
  18. 平台搭建_记一次CTFd平台搭建
  19. 【git】出现Merge Conflict,解冲突
  20. android tv重装系统,今日影视tv版app

热门文章

  1. 【游戏开发实战】使用Unity制作像天天酷跑一样的跑酷游戏——第二篇:使用Animator控制跑酷角色的动画状态切换
  2. 海上有网络吗?今天介绍下无线宽带自组网通信系统
  3. C++学校信息管理系统
  4. 今日头条自媒体运营推广视频教程学习资料短视频运营从零到精通 今日头条趣东方头条凤凰新浪看点网...
  5. WePhone开发者苏享茂被逼自杀,背后或有团伙?世纪佳缘责任多大?
  6. 2023年1月国内外量子科技进展
  7. Python SQLAlchemy Alembic的使用
  8. 华科大考研计算机系834大纲之计算机网络(二)
  9. PCIe及USB传输速度小结
  10. 纯css绘制的疲惫表情包