c入门第十三篇——字符数组放不下一个女生的名字

师弟:“师兄,我最近在学习字符串的操作,遇到一个奇怪的现象,你帮我看看。”
我:“好啊,你描述一下现象呢?”
师弟:“我给一个字符串赋值,结果影响了另外一个整型的数值。程序简化如下。”

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

int main()
{
    long long a = 2;
    char name[8];
    strcpy(name, "chengxia");
    printf("name: %s\n", name);
    printf("a: %lld\n", a);

    return 0;
}

我:“你这是字符串溢出了。”
师弟:“溢出了?我定义的数组大小为8,赋值的字符串长度也为8,怎么会溢出呢?”
我:“在C语言中,字符串以空字符 ‘\0’ 结尾,所以它尾部还有一个隐形的字符。”
Linux系统可以通过man strcpy来看一下函数帮助,帮助中说明了会一并将’\0’进行拷贝,故溢出了。

DESCRIPTION
The strcpy() function copies the string pointed to by src, including the terminating null byte (‘\0’), to the buffer pointed to by dest. The strings may not overlap, and the
destination string dest must be large enough to receive the copy. Beware of buffer overruns! (See BUGS.)

然后可以通过打印地址信息,也可以发现地址的确溢出了。

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

int main()
{
    long long a = 2;
    char name[8];
    strcpy(name, "chengxia");
    printf("name: %s\n", name);
    printf("a: %lld\n", a);
    printf("%p %p %p\n", &name, &name[7], &a);//打印地址信息

    return 0;
}

字符串

早之前也说到,在C语言中,没有直接支持字符串类型,字符串是字符的序列,以空字符 ‘\0’ 结尾。这个空字符不是数字0,而是ASCII码中值为0的字符,用于标记字符串的结束。通常是通过字符数组或指向字符的指针来操作字符串。
字符串的几种表达形式如下:

char str[6] = {'h', 'e', 'l', 'l', 'o', '\0'};
char str[] = "hello"; //字符数组
char *str = "hello"; //字符指针
#define HELLO "hello" //宏定义

在使用字符串的时候,要时刻牢记字符串结束符’\0’。
C语言的标准库(<string.h>)提供了一些函数来操作字符串,在Linux系统中,可以通过man来看函数的用法。

函数功能
strcpy(dst, src)/strncpy(dst, src, n)字符串拷贝
strcat(dst, src)/strncat(dst, src, n)字符串拼接
strlen(s)字符串长度
strcmp(s1, s2)/strcnmp(s1, s2, n)字符串比较
strchr(s, c)/strrchr(s, c)c在s中第一次(最后一次)出现的位置
strstr(s1, s2)/strcasestr(s1, s2)子串判断

在做字符串拷贝的时候,一般首选strncpy,防止缓冲区溢出。

strcpy 和 memcpy比较
这两个函数都能进行字符串的copy,但是memcpy又不仅仅局限于字符串的copy,memcpy功能更广,主要是进行内存字节级拷贝。
strcpy会默认赋值’\0’,但是memcpy不会。
用这2个函数实现字符串的拷贝,示例如下:

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

void name_strcpy(char *s)
{
    char name[16];
    strcpy(name, s);
    printf("name: %s\n", name);
}

void name_memcpy(char *s)
{
    char name[16];
    int len = strlen(s);
    memcpy(name, s, len);
    name[len] = '\0';
    printf("name: %s\n", name);
}

int main()
{
    char name[] = "chengxia";
    name_strcpy(name);
    name_memcpy(name);
    return 0;
}

题外

我:“chengxia是谁?”
师弟哈哈一笑:“就是那个给我出题的女生。”

ascii表: https://baike.baidu.com/item/ASCII/309296?fr=ge_ala

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值