C语言char s[]和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的区别的文章就介绍到这了,更多相关C语言 char s[]和char* s内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 使用C语言递归与非递归实现字符串反转函数char *reverse(char *str)的方法

    代码如下所示: 复制代码 代码如下: // 递归实现字符串反转   char *reverse(char *str)   {    if( !str )    {     return NULL; } int len = strlen(str);       if( len > 1 )       {           char ctemp =str[0];           str[0] = str[len-1];              str[len-1] = '/0';// 最后一

  • 基于C语言char与unsigned char的区别介绍

    在C中,默认的基础数据类型均为signed,现在我们以char为例,说明(signed) char与unsigned char之间的区别. 首先在内存中,char与unsigned char没有什么不同,都是一个字节,唯一的区别是,char的最高位为符号位,因此char能表示-127~127,unsigned char没有符号位,因此能表示0~255,这个好理解,8个bit,最多256种情况,因此无论如何都能表示256个数字. 在实际使用过程种有什么区别呢?主要是符号位,但是在普通的赋值,读写文

  • C语言变长数组 struct中char data[0]的用法详解

    今天在看一段代码时出现了用结构体实现变长数组的写法,一开始因为忘记了这种技术,所以老觉得作者的源码有误,最后经过我深思之后,终于想起以前看过的用struct实现变长数组的技术.下面是我在网上找到的一篇讲解很清楚的文章. 在实际的编程中,我们经常需要使用变长数组,但是C语言并不支持变长的数组.此时,我们可以使用结构体的方法实现C语言变长数组. struct MyData { int nLen; char data[0];}; 在结构中,data是一个数组名:但该数组没有元素:该数组的真实地址紧随结

  • C语言中判断一个char*是不是utf8编码

    C语言中判断一个char*是不是utf8编码 里我修改了一下, 纯ASCII编码的字符串也返回true, 因为UTF8和ASCII兼容 实例代码: int utf8_check(const char* str, size_t length) { size_t i; int nBytes; unsigned char chr; i = 0; nBytes = 0; while (i < length) { chr = *(str + i); if (nBytes == 0) { //计算字节数 i

  • C#语言中字符类char的使用方法(总结)

    char类在C#中表示一个unicode字符,正是这些unicode字符构成了字符串.unicode字符是目前计算机中通用的字符编码,它为针对不同语言中的每个字符设定了统一的二进制编码,用于满足跨越语言.跨平台的文本转换.处理要求.char的定义非常简单,如下: char ch1='z': 但是,char只能定义一个unicode字符. 下面是char类常见的使用方法及说明 iscontrol   指示指定的unicode字符是否属于控制字符类别 isdigit  指示某个unicode字符是否

  • C语言char s[]和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.指针 指针也是一种变量,只不过它的内存

  • C语言详解用char实现大小写字母的转换

    目录 一.例题 二.例题 三.总结 一.例题 将多个字母进行小写转换成大写 代码: #include <stdio.h> int main (void) { char a,b,c,d; //定义一个四个字符量 printf("请输入你想要的四个小写字母:"); scanf("%c%c%c%c",&a,&b,&c,&d); //在键盘输入得到想要的四个字母 a=a-32; //通过ASCII得到字母相差数 b=b-32; c

  • SQL2005中char nchar varchar nvarchar数据类型的区别和使用环境讲解

    现在就摘录一下sql2005联机丛书里的关于这几个数据类型的解释 字符数据类型(nchar 长度固定,nvarchar 长度可变)和 Unicode 数据使用 UNICODE UCS-2 字符集. nchar [ ( n ) ] n 个字符的固定长度的 Unicode 字符数据.n 值必须在 1 到 4,000 之间(含).存储大小为两倍 n 字节.nchar 的 SQL-2003 同义词为 national char 和 national character. nvarchar [ ( n |

  • char str[] 与 char *str的区别详细解析

    复制代码 代码如下: char* get_str(void)  {      char str[] = {"abcd"};      return str;  } char str[] = {"abcd"};定义了一个局部字符数组,尽管是数组,但它是一个局部变量,返回它的地址肯定是一个已经释放了的空间的地址. 此函数返回的是内部一个局部字符数组str的地址,且函数调用完毕后 此数组被销毁,所以你返回的指针也就指向一块被销毁的内存,这种写法是错误的. 复制代码 代码如

  • 浅析char 指针变量char *=p 这个语句的输出问题

    学习指针的时候我一直有个疑惑,请看下面的代码: #include <iostream> using std::cout; void main() { int num=5; int *nPtr=&num; cout<<nPtr;//输出指针的地址.但是会报错<<没有直接输出int *地址的功能 return ; } 但是,将int 改成char 类型就不会报错,可以输出字符串.同样是指针,这次为何没有输出地址(理应输出指针代表的地址,但是<<并没有重载

  • C++中char[]能修改char*却不行

    少扯淡没用的,直接上代码 int main(int argc, char *argv[]) { char p[74] = "abcefghijkmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm"; char *a = "abcefghijkmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm"; printf(&qu

  • C++中const char*、char const*、char * const三者的区别

    目录 一.const char *ptr; 二.char const *ptr; 三.char * const ptr; C/C++ 中关于以下三种定义: const char *ptr; char const *ptr; char * const ptr; 整理三者之间的区别与联系. 一.const char *ptr; 定义一个指向字符常量的指针,这里,ptr是一个指向 char* 类型的常量,所以不能用ptr来修改所指向的内容,换句话说,*ptr的值为const,不能修改.但是ptr的声明

随机推荐