目录
目录
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
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
3
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都是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