微信原文

你知道char *s和char s[]的区别吗?​mp.weixin.qq.com

在一个夜深人静的晚上,有一个读者给我发了一个C语言题目。他问我,发哥,帮我看看这个代码有什么问题。我看了代码之后,心里一阵恐慌。我自认为我不是C语言高手。但是我确实是一个喜欢解决问题的男人。就是在这样的背景驱使下,我写下了这篇文章。

char *str1 = "hello";
char str2[] = "hello";

我们看这两个定义。我们说这个是定义而不是声明,是因为定义在内存里面分配了房子。而声明,只给了个房产证却不给你分房子。

str1 这个类型是 char * 。它是一个指针,这个指针指向一个字符串。 str2 这个类型是 char [] 。它是一个数组,他代表了这堆内存空间。

“hello”字符串在内存中是这样存放的

我之前写过一个地址分配的文章,str1 str3都是指向字符串的指针,而且这个字符串是保存在字符串常量区的。这个常量区里面的东西是不能被修改的。编译器让他们指向了同一个地址。这个地址保存的东西是 “hello”这个字符串。

大家看看下面这个代码有什么问题?

#include "stdio.h"
#include "stdlib.h"
#include "string.h"int main(void)
{char *str1 = "hello"; char *str3 = "hello";char str2[] = "hello";memcpy(str3,"worldtest",strlen("worldtest")+1);printf("str1:%s str3:%s str2:%sn",str1,str3,str2);str3 = "world";printf("str1:%s str3:%s str2:%sn",str1,str3,str2);printf("hello,worldn");return (0);
}

如果改成这样的呢?应该输出什么结果呢?

#include "stdio.h"
#include "stdlib.h"
#include "string.h"int main(void)
{char *str1 = "hello"; char *str3 = "hello";char str2[] = "hello";//memcpy(str3,"worldtest",strlen("worldtest")+1);printf("str1:%s str3:%s str2:%sn",str1,str3,str2);str3 = "world";printf("str1:%s str3:%s str2:%sn",str1,str3,str2);printf("hello,worldn");return (0);
}

我之前在文章里面讨论一个问题,我们说指针的时候,要说指针变量。保存地址的是一个地址。这个地址保存的地址是可以变化的。只要类型符合。都可以保存起来。

同样的,在上面的例子中,如果我们尝试这样

str1[1] = 'a';

这样也是错误的。

试试下面这段代码

#include <stdio.h>
int main(){char* str1="Hello";printf("nstr1: %s, address: %p, sizeof(str1): %u", str1, str1, sizeof(str1));str1 = "world";printf("nstr1: %s, address: %p, sizeof(str1): %u", str1, str1, sizeof(str1));return 1;
}

输出

str1: Hello, address: 0000000000404000, sizeof(str1): 8
str1: world, address: 0000000000404031, sizeof(str1): 8
--------------------------------
Process exited after 0.0226 seconds with return value 1
请按任意键继续. . .

通过赋值运算后,str1的值也发生了改变。

但是str2情况会不一样,str2是一个数组。

既然是数组,我们看看这段小代码

#include<stdio.h>
int main(){char str2[] = "hello";printf("nstr2: %s, address: %p, sizeof(str2): %u", str2, str2, sizeof(str2));str2[2] = 'A';printf("nstr2: %s, address: %p, sizeof(str2): %u", str2, str2, sizeof(str2));strcpy(str2, "world");printf("nstr2: %s, address: %p, sizeof(str2): %u", str2, str2, sizeof(str2));return 1;
}

输出日志

str2: hello, address: 000000000062FE10, sizeof(str2): 6
str2: heAlo, address: 000000000062FE10, sizeof(str2): 6
str2: world, address: 000000000062FE10, sizeof(str2): 6
--------------------------------
Process exited after 0.04063 seconds with return value 1
请按任意键继续. . .

送一个图

晚上回来我写了一个小程序。大家看看

#include <stdio.h>
#include "stdlib.h"
#include "string.h"const int a = 1;
const int a1 = 1;
char * s = "hello";int main()
{const int b = 2;const int b1 = 2;char * s1 = "hello";printf("s:%p s1:%pn",s,s1);printf("a:%p a1:%p b:%p b1:%pn",&a,&a1,&b,&b1);return 1;
}

输出如下:

s:0000000000404008 s1:0000000000404008
a:0000000000404000 a1:0000000000404004 b:000000000062FE14 b1:000000000062FE10--------------------------------
Process exited after 0.03901 seconds with return value 1
请按任意键继续. . .

可以看到,s,s1,a,a1都是在一个内存区域。这个内存区域的内容是不允许改变的。如果你对这里的内存区域赋值,就会出现段错误。

但是b和b1这个内存区域大家看看。我们可以写个小代码测试一下。

#include <stdio.h>
#include "stdlib.h"
#include "string.h"const int b = 2;int main()
{const int b1 = 2;int *p = &b1; printf("b1:%dn",b1);*p = 3;printf("b1:%dn",b1);return 1;
}

输出:

b1:2
b1:3--------------------------------
Process exited after 0.0403 seconds with return value 1
请按任意键继续. . .

但是我们写成这样呢?

#include <stdio.h>
#include "stdlib.h"
#include "string.h"const int b = 2;int main()
{const int b1 = 2;int *p = &b; printf("b:%dn",b);*p = 3;printf("b:%dn",b);return 1;
}

输出:

b:2--------------------------------
Process exited after 3.743 seconds with return value 3221225477
请按任意键继续. . .

如果放到gcc下,可以看到,执行到代码

*p = 3;

会出现段错误。因为访问了不能访问的地址。这也就是我们很多时候给空指针赋值出现段错误的原因。操作了非法的地址。

好了,就瞎BB这么多,如果觉得有用,可以留言一起讨论下。

void readstring( char s[] ); 怎样_char *s和char s[]相关推荐

  1. c语言char数字转int补位,关于char强制转换成int到底是用0还是用1补位的猜想与检验...

    关于char强制转换成int到底是用0还是用1补位的猜想与检验 最近学C语言发现char强制转换时值会完全不同,而且变化很大,于是决定写代码测试一下. 先检验一下char型的-3和3在内存中分别怎么表 ...

  2. c语言中将整数转换成字符串_在C语言中将ASCII字符串(char [])转换为八进制字符串(char [])...

    c语言中将整数转换成字符串 Given an ASCII string (char[]) and we have to convert it into octal string (char[]) in ...

  3. char 转wchar_t 及wchar_t转char

    利用widechartomultibyte来转换的函数 通常适合于window平台上使用 #include <tchar.h> #include <windows.h> int ...

  4. char qt 转unicode_Qt QString 中文 char* UTF-8 QByteArray QTextCodec unicode gb2312 GBK 乱码与转码问题...

    2012-03-22 14:00 175人阅读 评论(0) 代码如下:如果不不设全局的字符集是utf-8,那么网上一般的方法是可以转的.如下程序中 #define DD 1的情况下:但是如果设置了全局 ...

  5. c语言中将整数转换成字符串_在C语言中将ASCII字符串(char [])转换为十六进制字符串(char [])...

    c语言中将整数转换成字符串 Given an ASCII string (char[]) and we have to convert it into Hexadecimal string (char ...

  6. Java char转换为String,String转换为char数组

    Today we will look into java char to String program. We will also learn how to convert String to a c ...

  7. char数组转换成字符串_将字符串转换为char数组java –将字符串转换为char

    char数组转换成字符串 Sometimes we have to convert String to the character array in java programs or convert ...

  8. c语言char输出字母,C语言unsigned char与char之间的转换及英文字符ASCII码和汉字内码输出...

    对于只认识0和1的机器来说是无法直接识别字符及汉字的.将ASCII表的高128个很少用到的数值以两个为一组来表示汉字,即汉字的内码.而剩下的低128位则留给英文字符使用,即英文的内码.如下程序所示: ...

  9. mysql int char连接_MySQL中int、char以及varchar的性能比较

    软件安装:装机软件必备包 SQL是Structured Query Language(结构化查询语言)的缩写.SQL是专为数据库而建立的操作命令集,是一种功能齐全的数据库语言.在使用它时,只需要发出& ...

最新文章

  1. 【ACM】熊孩子的乐趣
  2. saltstack pkg模块用法
  3. Office 365强势来袭PART1:云中Outlook体验
  4. tcpdump dns流量监控
  5. Android java.lang.UnsatisfiedLinkError
  6. c++11-decltype
  7. 学计算机写作文怎么写,关于学电脑的作文
  8. java 开源地图引擎_开源三维地图框架-Cesium
  9. 甲骨文中国确认裁员 900 余人;网易回应邮箱账号遭公开叫卖;我国网民达 8.29 亿 | 极客头条...
  10. 首个教育部印发的人工智能行动计划出炉:规划三步走,大学有三任务
  11. 用python爬取杭电oj的数据
  12. 数据类产品设计和实现思路
  13. Android 获取assets文件夹下面的文件路径
  14. 基于socket(TCP)和opencv的实时视频传输
  15. 嵌入式Linux内核配置、裁剪与编译浅析(ARM版)
  16. mysql count统计
  17. 谷粒商城-基础篇-环境搭建(P1-P44)
  18. 【机器学习】EM 算法
  19. 挣值如何计算?(转载)
  20. Android8.1 开关VOLTE流程分析

热门文章

  1. php软件开发--sphinx索引静态化及伪静态
  2. 交换ctrl和左caps_如何在Linux中交换Ctrl和Caps Lock键
  3. wire 和 reg_Wire和Launchkit开源,水流监控系统以及更多新闻
  4. 帮助中心 开源_如何不获得开源帮助
  5. Hacktoberfest活动导致GitHub捐款近5万
  6. 教程 | 叮咚!答应你们的文件上传教程,到货了!
  7. JavaScript中语句与函数的执行辨析
  8. 视觉SLAM笔记(26) 状态估计问题
  9. linux发展前景2018,2018 年 Linux 的 8 个发展预测
  10. mysql innodb和myisam区别_MySQL?存储引擎简介