strlen/sizeof/static/strcpy/strcmp/strcat/strstr/snprintf

目录

目录

strlen/sizeof

static关键字

strcpy

strcmp

strcat

strstr

memcmp

snprintf


strlen/sizeof

strlen是一个预定义的函数,它的定义包在string.h头文件中,strlen的主要任务是计算一个以'\0'结尾的字符串的长度,如:char str[20] = "hello"; //strlen(str) = 5;(因为这个字符串有5个字符,h e l l o \0)。

sizeof是一个编译时的运算符,它可以计算任何类型或变量的大小,

sizeof用于类型:sizeof(type)

sizeof用于变量:sizeof(var)或sizeof val

如:

char str[20] = "hello"; //sizeof(str) = 20;

char str[] = "hello"; //sizeof(str) = 6;

strlen只关心字符串实际存在的字符数量,sizeof只关心数据类型或变量所占用的内存空间。


1.sizeof会将空字符\0计算在内,而strlen不会将空字符\0计算在内。

2.sizeof是操作符(关键字),它结果类型是size_t,它在头文件中typedef为unsigned_int类型。 strlen是函数。

3.sizeof可以用类型做参数,strlen只能用char*做参数,且必须是以''\0''结尾的。

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

int main(void)
{
	char str1[20] = "hello";
	
	printf("sizeof(str1) = %d\n",(int)sizeof(str1));
	printf("strlen(str1) = %d\n",(int)strlen(str1));
	
	return 0;
}

CLC@Embed_Learn:~/file$ gcc 1.c 
CLC@Embed_Learn:~/file$ ./a.out 
sizeof(str1) = 20
strlen(str1) = 5

4.数组做sizeof的参数不退化,传递给strlen就退化为指针了。

5.大部分编译程序 在编译的时候就把sizeof计算过了是类型或是变量的长度这就是sizeof(x)可以用来定义数组维数的原因

6.strlen的结果要在运行的时候才能计算出来,是用来计算字符串的长度,不是类型占内存的大小。  

7.sizeof后如果是类型必须加括弧,如果是变量名可以不加括弧。这是因为sizeof是个操作符不是个函数。

8.当适用了于一个结构类型时或变量, sizeof 返回实际的大小,当适用一静态地空间数组, sizeof 归还全部数组的尺寸。

资料扩展

sizeof的功能是计算一个数据类型的大小,这个类型可以是数组、函数、指针、对象等,单位为字节,它的返回值是size_t类型,也就是unsigned int类型,是一个无符号整数。注意:sizeof不是一个函数,它是一个运算符,所以它不需要包含任何头文件。

编辑

strlen的功能是计算一个指定字符串的长度,函数原型是size_t strlen(const char *s),它的返回值是size_t类型,也就是unsigned int类型,返回的是字符串的长度,需要包含头文件#inlude <string.h>,参数s是字符串首地址。

static关键字

1. 修饰局部变量,在整个程序运行期间存在,程序运行结束后自动释放。

#include<stdio.h>

void tesk()
{
        int i = 0;
        i = i + 1;
        printf("%d\n", i);
}

int main(int argc, char *argv[])
{
        int n = 0;
        while(n < 3){
                tesk();
                n++;
        }

        return 0;
}

1

1

加上static关键字之后,该局部变量为“静态局部变量” 

#include<stdio.h>

void tesk()
{
        static int i = 0;
        i = i + 1;
        printf("%d\n", i);
}

int main(int argc, char *argv[])
{
        int n = 0;
        while(n < 3){
                tesk();
                n++;
        }

        return 0;
}

1

2


2. 修饰全局变量,会把全局变量私有化,只能在本文件中调用,其他文件中调用不到。

#include <stdio.h>

static int a = 10;

void tesk1()
{
	a = a + 1;
	printf("%d\n", a);
}

void tesk2()
{
	a = a + 1;
	printf("%d\n", a);
}
int main()
{
	tesk1();

	tesk2();

	return 0;
}

11

12 


3. 修饰函数,会把该函数变为内部函数,只能在本文件中调用,其它外部文件中调用不到,同全局变量一样。

#include <stdio.h>

static int a = 10;

static void tesk1()
{
	a = a + 1;
	printf("%d\n", a);
}

void tesk2()
{
	a = a + 1;
	printf("%d\n", a);
}
int main()
{
	tesk1();

	tesk2();

	return 0;
}

strcpy、strncpy、memcpy

char* strcpy(char* destination,const char* source);

strcpy()函数:是覆盖拷贝,将source全覆盖拷贝到destination,会把’\0’也拷过去,且必须考虑destination的空间够不够
(destination的空间必须>=source的空间)

strncpy()函数: 是 C语言的库函数之一,来自 C语言标准库,定义于 string.h,char *strncpy(char *dest, const char *src, int n),把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,并返回dest。

#include <stdio.h>
#include <string.h>
int main()
{	
	char str[128] = {'\0'};
    char *p = "1234567890";
	
	strcpy(str,p);
	puts(str);
	memset(str, '\0', sizeof(str));
	strncpy(str,p,6);
	puts(str);
	
	return 0;
}

gcc xxx.c

a.exe

1234567890
123456

strcpy memcpy区别

strcpy和memcpy都是‌C语言中的库函数,用于内存操作,但它们的功能和用途有所不同。‌‌12

strcpy主要用于字符串的拷贝,只能拷贝字符串类型的数据。它的函数原型是char *strcpy(char *strDest, const char *strSrc)。strcpy在拷贝过程中遇到字符串结束符\0时停止,因此不需要指定拷贝的长度。由于strcpy不检查目的地址的内存是否足够,如果源字符串长度超过目的地址的容量,就会导致缓冲区溢出,从而引发安全问题。

memcpy则用于内存的拷贝,可以拷贝任意类型的数据,包括字符串。它的函数原型是void *memcpy(void *dest, const void *src, size_t count)。memcpy根据第三个参数决定拷贝的长度,因此需要明确指定拷贝的字节数。由于memcpy会严格按照指定的长度进行拷贝,不会自动停止,因此更加安全可靠。

总结来说,strcpy适用于简单的字符串拷贝场景,而memcpy则适用于需要拷贝任意类型数据的场景,更加灵活和安全。


strcpy、strncpy和memcpy区别

主要是strcpy和mencpy的区别

    strcpy和memcpy都是标准C库函数,它们有下面的特点。

    strcpy提供了字符串的复制。即strcpy只用于字符串复制,并且它不仅复制字符串内容之外,还会复制字符串的结束符。memcpy提供了一般内存的复制。即memcpy对于需要复制的内容没有限制,因此用途更广

1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。

3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy

使用情况:
1、dest指向的空间要足够拷贝;使用strcpy时,dest指向的空间要大于等于src指向的空间;使用strncpy或memcpy时,dest指向的空间要大于或等于n。

2、使用strncpy或memcpy时,n应该大于strlen(src),或者说最好n >= strlen(s1)+1;这个1 就是最后的“\0”。
3、使用strncpy时,确保dest的最后一个字符是“\0”。

代码示例:

strcpy源码:

char * strcpy(char * dest, const char * src) // 实现src到dest的复制
{
  if ((src == NULL) || (dest == NULL))     //参数判空
  {
      return NULL;
  }
  char *strdest = dest;                             //保存目标字符串的首地址
  while ((*strDest++ = *strSrc++)!='\0'); //把src字符串的内容复制到dest下
  return strdest;
}

strncpy源码:

char *strncpy(char *dest, const char *src, int len)
{     
    assert(dest!=NULL && src!=NULL);      
    char *temp;     
    temp = dest;     
    for(int i =0;*src!='\0' && i<len; i++,temp++,src++)          
        *temp = *src;    
    *temp = '\0';     
    return dest; 
}

memcpy源码:

void *memcpy(void *memTo, const void *memFrom, size_t size)
{
  if((memTo == NULL) || (memFrom == NULL))   //memTo和memFrom必须有效
         return NULL;
  char *tempFrom = (char *)memFrom;                //保存memFrom首地址
  char *tempTo = (char *)memTo;                         //保存memTo首地址      
  while(size -- > 0)                                                //循环size次,复制memFrom的值到memTo中
         *tempTo++ = *tempFrom++ ;  
  return memTo;
}

strcmp、strncpy

int strcmp ( const char * str1, const char * str2 );

strcmp比较两个字符串的大小,一个字符一个字符比较,按ASCLL码比较
标准规定:
第一个字符串 > 第二个字符串,则返回 > 0的数字
第一个字符串 = 第二个字符串,则返回0
第一个字符串 < 第二个字符串,则返回 < 0的数字

#include<stdio.h>
#include<string.h>
int main()
{
	char* p1 = "abcdef";
	char* p2 = "abcdef";
	char* p3 = "abcd";
	char* p4 = "bcde";
	printf("strcmp(p1, p2) = %d\n", strcmp(p1, p2));
	printf("strcmp(p1, p3) = %d\n", strcmp(p1, p3));
	printf("strcmp(p3, p4) = %d\n", strcmp(p3, p4));
}

strcmp(p1, p2) = 0
strcmp(p1, p3) = 1
strcmp(p3, p4) = -1

strcat、strncat

char *strcat(char *dest, const char *src)

strcat追加拷贝,追加到目标空间后面,目标空间必须足够大,能容纳下源字符串的内容

#include<stdio.h>
#include<string.h>
int main()
{
	char p1[20] = "hello";
	const char* p2 = " world";

	strcat(p1, p2);
	printf("p1 = %s\n",p1);

	return 0;
}

p1 = hello world 

strstr

char *strstr( const char *str1, const char *str2 );

strstr函数是在字符串str1中查找是否含有字符串str2,如果存在,返回str2在str1首次出现的地址;否则返回NULL。

#include<stdio.h>
#include<string.h>
 
//strstr函数的应用
int main()
{
	char arr1[] = "abbbcdef";
	char arr2[] = "bbc";
 
	printf("strstr(arr1, arr2) = %s\n", strstr(arr1, arr2));
 
	return 0;
}

strstr(arr1, arr2) = bbcdef

memcmp

int memcmp(const void *str1, const void *str2, size_t n);

其功能是把存储区 str1 和存储区 str2 的前 n 个字节进行比较。该函数是按字节比较的,位于string.h。

函数原型:int memcmp(const void *str1, const void *str2, size_t n);

参数:

  • str1-- 指向内存块的指针。

  • str2-- 指向内存块的指针。

  • n-- 要被比较的字节数。

功能:比较内存区域buf1和buf2的前count个字节。

头文件:#include <string.h>或#include<memory.h>

返回值:

  • 如果返回值 < 0,则表示 str1 小于 str2。

  • 如果返回值 > 0,则表示 str1 大于 str2。

  • 如果返回值 = 0,则表示 str1 等于 str2。

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

int main()
{

	char *s1 = "abc";
	char *s2 = "acd";
	int r = memcmp(s1,s2,3);

	printf("r = %d", r);

	return 0;
}

输出结果:
r = -257
#include<string.h>
#include<stdio.h>

int main()
{
    char *s1 = "Hello,Programmers!";
    char *s2 = "Hello,Programmers!";
    int r;
    r = memcmp(s1,s2,strlen(s1));
    if(!r)
        printf("s1 and s2 are identical\n");/*s1等于s2*/
    elseif(r<0)
        printf("s1 is less than s2\n");/*s1小于s2*/
    else
        printf("s1 is greater than s2\n");/*s1大于s2*/
    return 0;
}


输出结果:
s1 and s2 are identical
请按任意键继续...

sprintf、snprintf

int snprintf(char *str, size_t size, const char *format, ...)

uint16_t len = strlen(json_str); 
char buf[256];
snprintf(buf, 256, "len=%ld", len );
HAL_UART_Transmit(&UartHandle, (uint8_t *)buf, strlen(buf), 100);

snprintf 函数用法详解_引壶觞以自酌,眄庭柯以怡颜的博客-CSDN博客

两点注意:

(1) 如果格式化后的字符串长度 < size,则将此字符串全部复制到str中,并给其后添加一个字符串结束符('\0');

(2) 如果格式化后的字符串长度 >= size,则只将其中的(size-1)个字符复制到str中,并给其后添加一个字符串结束符('\0'),返回值为欲写入的字符串长度。

使用snprintf函数时要注意上面两点,这是我看过无数使用这个函数的程序员绝大部分都存在的两点隐患:

比如:

char buf[LEN];
int n = snprintf(buf, LEN, "%s%d%s", str1, int2, str3);
printf("total length n %d"\n, n);

snprintf的返回值是欲写入的字符串长度,而不是实际写入的字符串度。如:

char buf[8];
int n = snprintf(buf, 5, "abcdefghijk");
printf("n %d    buf %s\n", n, buf);
 
运行结果为:
n 11     buf abcd

注意这个结果,只输出了abcd,长度为4,不是期待的5,没有输出 e ,说明snprintf函数最后自动加上去的'\0',是算在size内部的,是格式化字符串的总长度(不包括'\0'),这里使用sizeof(buf)时需要注意+1,这一点与malloc申请空间类似。

总结:

1.snprintf会自动在格式化后的字符串尾添加\0,结尾符是包含在size长度内部的。

2.snprintf会在结尾加上\0,不管buf空间够不够用,所以不必担心缓冲区溢出。

3.snprintf的返回值n,当调用失败时,n为负数,当调用成功时,n为格式化的字符串的总长度(不包括\0),当然这个字符串有可能被截断,因为buf的长度不够放下整个字符串。

可以判断输出
if ( n < 0) : snprintf出错了
if ( n >0 && n < sizeof(buf) ) : snprintf成功,并且格式了完成的字符串。
if ( n >= sizeof(buf) ) : snprintf成功,但要格式化的字符串被截断了。
 

 1 #include<stdio.h>
    2 
    3 int main()
    4 {
    5     char buffer[10]; //定义一个只有10个字节空间的buffer数组
    6     const int a = 12345; //定义一个int型的常量
    7     //const char *msg = "012345678901234567890"; //定义一个长度为20字节的字符串常量
    8     const char *msg = "88888"; //定义一个长度为20字节的字符串常量
    9 
   10     //sprintf(buffer, "%d", a); //将a变量按int类型打印成字符串,输出到buffer中
   11     //printf("buffer = %s", buffer);    
   12 
   13 
   14     
w  15     snprintf(buffer, sizeof(buffer), "%d+%s", a, msg); //将a变量按int类型打印成字符串,输出到buffer中
   16     printf("buffer = %s", buffer);
   17     return 0;
   18 }

输出结果:
buffer = 12345
输出结果:
buffer = 12345+888

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值