鱼C论坛

 找回密码
 立即注册
查看: 1964|回复: 15

[已解决]有没有大佬讲解一下为什么要-1啊

[复制链接]
发表于 2022-4-23 14:24:27 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
看了好多遍还是没有理解,这个减一有什么用,好像都一样吧?
最佳答案
2022-4-24 15:45:11
1613551 发表于 2022-4-24 13:03
但是,我试了一下,就算不留个位置给\0,程序也能正常打印诶?

的确,strcat是会自动在末尾追加\0,虽然10字节空间已经被占满了,最后的\0还是会放在紧接在这10字节后面的一字节空间内,这并不是数组str的内存空间了。
而按%s打印,实际上是传一个首地址开始读数据,读到\0就认为结束了,并不会检查是不是超过了str的空间。

虽然能打印出正确结果,但绝对不要这么做
一是因为内存里具体怎么存放数据,哪个数据放在了哪个地址里,这都是系统做的事,对程序员是不可见的,万一紧接在str后面的内存空间存放着有用的数据,你这\0一过去就覆盖破环了原数据,后果是无法估计的。
二是假设你认为了str[10]这空间里面存放的就是完整字符串了,如果将它逐一字符的放进另一个10字节大小的空间,这时候新的那片空间之后的可就不一定是\0了,再想以字符串完整输出肯定会多出一片乱码
uTools_1650694952518.png
uTools_1650694925068.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-4-23 14:28:49 | 显示全部楼层
因为下标是以 0 开始的,而字符数组的大小是从 1 开始算的,当然要减1了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-4-23 14:34:47 | 显示全部楼层
isdkz 发表于 2022-4-23 14:28
因为下标是以 0 开始的,而字符数组的大小是从 1 开始算的,当然要减1了


不好意思,没看懂....下标是什么...就是可以举例一下吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-23 14:38:48 | 显示全部楼层
本帖最后由 isdkz 于 2022-4-23 14:42 编辑
1613551 发表于 2022-4-23 14:34
不好意思,没看懂....下标是什么...就是可以举例一下吗


下标也就是索引,表示第几个,str[0] 中的 0 就是下标,

在计算机中是以 0 开始的,不是以 1 开始的,

比如说 char str[10] 声明了一个长度为 10 的字符数组,

这个字符数组的第一个元素是 str[0],而不是 str[1],

所以第10个元素不是 str[10],而是 str[10 - 1],即 str[9]
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-4-23 14:57:25 | 显示全部楼层
isdkz 发表于 2022-4-23 14:38
下标也就是索引,表示第几个,str[0] 中的 0 就是下标,

在计算机中是以 0 开始的,不是以 1 开始的 ...

我好像有点懂了,你是说sizeof计算大小的时候会把\n也计算进去,所以为正确的计算出字符串的大小,所以应该-1,相当于把多计算的\n去掉吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-23 15:00:46 | 显示全部楼层
1613551 发表于 2022-4-23 14:57
我好像有点懂了,你是说sizeof计算大小的时候会把\n也计算进去,所以为正确的计算出字符串的大小,所以应 ...

不是,sizeof计算出来的就是字符串的长度了,因为字符的位置是从 0 开始算的,

而长度是从 1 开始算的,所以字符串的最后一个字符就是字符串的长度减 1 呀
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-4-23 15:10:27 | 显示全部楼层
isdkz 发表于 2022-4-23 15:00
不是,sizeof计算出来的就是字符串的长度了,因为字符的位置是从 0 开始算的,

而长度是从 1 开始算的 ...

这样的话我突然不是很理解为什么要用sizeof来计算,而不用strlen
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-23 15:13:49 | 显示全部楼层
1613551 发表于 2022-4-23 15:10
这样的话我突然不是很理解为什么要用sizeof来计算,而不用strlen

strlen得到的只是字符串的长度(不包括结束符\0),

而 sizeof 得到的是整个字符数组的长度
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-4-23 15:22:03 | 显示全部楼层
isdkz 发表于 2022-4-23 15:13
strlen得到的只是字符串的长度(不包括结束符\0),

而 sizeof 得到的是整个字符数组的长度

我没理解,如果是char类型的话,sizeof不就比strlen多获取了一个\n吗?然后还通过-1,然后减掉了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-23 19:40:18 | 显示全部楼层
1.sizeof所计算的是该变量的内存空间有多大(能放多少字节的数据)
2.字符串必须以'\0'结尾,否则编译器不会知道字符串是到哪里结束,'\0'也占着1字节的空间

在你的例子中,str数组有10字节的内存空间可用,也就是最多能放10字节的数据,1个字符占1字节空间
字符串"I love FishC.com!"长度是17,尺寸(所占空间)是18(含'\0')
str数组空间明显不够存放完整
本着能放多少就放多少的想法,就有了
strcat(str, "I love FishC.com!", sizeof(str))
也就是把字符串的前10个字符放进去,即"I love Fis"
但是这样一来str空间就被用完了,'\0'放不下去就出问题了
你或许可以通过str[i]的方式来逐一访问每一个字符,但是想要以%s一次性输出字符串就肯定不行,没有'\0'做结尾根本无法识别
综上,你必须留出最后一字节空间存放'\0'
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-24 09:49:12 | 显示全部楼层
strlen 函数用于返回指定字符串的长度。
C 语言字符串的长度取决于结束符('\0')的位置。     
                                                                       —— 小甲鱼
也就是说都会计算' \n '的

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-24 10:25:14 | 显示全部楼层

1.楼主应理解字符数组如何存放字符串
2.关于sizeof()和strlen()的区别,看一下这篇文章    https://www.cnblogs.com/caojun97/p/16129482.html
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-4-24 13:02:02 | 显示全部楼层
风车呼呼呼 发表于 2022-4-23 19:40
1.sizeof所计算的是该变量的内存空间有多大(能放多少字节的数据)
2.字符串必须以'\0'结尾,否则编译器不 ...

我懂了,就是strcat是会在末尾自动追加一个\0的,而数组的长度最大也才10,你又填了10个字符进来,那么就没有\0的位置了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-4-24 13:03:56 | 显示全部楼层
风车呼呼呼 发表于 2022-4-23 19:40
1.sizeof所计算的是该变量的内存空间有多大(能放多少字节的数据)
2.字符串必须以'\0'结尾,否则编译器不 ...

但是,我试了一下,就算不留个位置给\0,程序也能正常打印诶?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-24 15:45:11 | 显示全部楼层    本楼为最佳答案   
1613551 发表于 2022-4-24 13:03
但是,我试了一下,就算不留个位置给\0,程序也能正常打印诶?

的确,strcat是会自动在末尾追加\0,虽然10字节空间已经被占满了,最后的\0还是会放在紧接在这10字节后面的一字节空间内,这并不是数组str的内存空间了。
而按%s打印,实际上是传一个首地址开始读数据,读到\0就认为结束了,并不会检查是不是超过了str的空间。

虽然能打印出正确结果,但绝对不要这么做
一是因为内存里具体怎么存放数据,哪个数据放在了哪个地址里,这都是系统做的事,对程序员是不可见的,万一紧接在str后面的内存空间存放着有用的数据,你这\0一过去就覆盖破环了原数据,后果是无法估计的。
二是假设你认为了str[10]这空间里面存放的就是完整字符串了,如果将它逐一字符的放进另一个10字节大小的空间,这时候新的那片空间之后的可就不一定是\0了,再想以字符串完整输出肯定会多出一片乱码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-24 15:46:55 From FishC Mobile | 显示全部楼层
1613551 发表于 2022-4-24 13:03
但是,我试了一下,就算不留个位置给\0,程序也能正常打印诶?

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

int main()
{
    char a[5]="abcde";
    char a2[5]="abcd";
    size_t b=sizeof(a);
    size_t b2=sizeof(a2);
    int c=strlen(a);
    int c2=strlen(a2);
    printf("%s %d %d\n",a,b,c);
    printf("%s %d %d\n",a2,b2,c2);
    if(a[5]=='\0')
        printf("!");
    return 0;
}
你试试这个,看看sizeof和strlen得出结果的区别,sizeof得到的是整个字符数组的长度,但是strlen得到的是字符串的长度(不算\0)。字符串结尾都是\0,就算你不留空间它也是\0,但是可能会覆盖其他数据吧。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-10-5 20:26

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表