C语言知识点 – 数据存储、字符串与内存操作函数
文章目录
一、数据存储
1.大小端
大端模式是指数据的低位保存在内存的高地址中,高位保存在内存的低地址中;
小端模式是指数据的低位保存在内存的低地址中,高位保存在内存的高地址中。
判断大小端的程序:
//查看整形数据的第一个字节
int check_sys()
{
int a = 1;
char* p = (char*)&a;
if (1 == *p)
{
return 1;//小端
}
else
{
return 0;//大端
}
}
2.练习
代码如下:
int main()
{
char a = -128;
printf("%u\n", a);
//-128补码:11111111111111111111111110000000
//截断 a:10000000
//以%u打印,无符号整数,发生整型提升
//char是有符号的,a前面按符号位提升
//11111111111111111111111110000000 -- 认为是无符号数打印
//结果为:4294967168
char b = 128;
printf("%u\n", b);
//b的打印结果为:4294967168
return 0;
}
二、字符串函数与内存操作函数
1.字符串长度strlen
1.strlen函数返回的是’\0’以前出现的字符的个数,不包含\0;
2.参数指向的字符串必须要以’\0’结尾;
3.函数的返回值是size_t类型的,是无符号的。
模拟实现strlen,代码如下:
size_t my_strlen(const char* str)
{
int count = 0;
assert(str != NULL);
while (*str != '\0')
{
count++;
str++;
}
return count;
}
2.字符串拷贝strcpy
1.源字符串必须以’\0’结尾;
2.会将源字符串的’\0’拷贝到目标空间;
3.目标价空间必须足够大,否则可以拷贝过去,但是会报错;
4.目标空间必须可变,不能是常量字符串。
模拟实现strcpy,代码如下:
char* my_strcpy(char* dst, const char* src)
{
assert(dst && src);
char* ret = dst;
while (*dst++ = *src++)
{
;
}
return ret;
}
3.字符串追加strcat
1.会追加到目标字符串的’\0’处(覆盖’\0’),且源字符串必须以’\0’结尾;
2.目标价空间必须足够大;
3.目标空间必须可修改;
模拟实现strcat,代码如下:
char* my_strcat(char* dst, const char* src)
{
assert(dst && src);
char* ret = dst;
while (*dst)
{
dst++;
}
while (*dst++ = *src++)
{
;
}
return ret;
}
4.字符串比较strcmp
1.不是比较字符串的长度,而是比较字符串对应位置上字符的大小,如果相同,就比较下一对,直到遇到不同或都遇到’\0’;
2.若第一个字符串大于第二个字符串,则返回大于0的数字;
若第一个字符串小于第二个字符串,则返回小于0的数字;
若第一个字符串等于第二个字符串,则返回0。
模拟实现strcmp, 代码如下:
int my_strcmp(const char* s1, const char* s2)
{
assert(s1 && s2);
while (*s1 == *s2)
{
if (*s1 == '\0')
{
return 0;//相等
}
s1++;
s2++;
}
if (*s1 > *s2)
{
return 1;
}
else
{
return -1;
}
}
5.长度受限的字符串拷贝strncpy
1.拷贝count个字符从源字符串到目标空间;
2.若源字符串长度小于count,则会在目标后面追加’\0’,知道count个。
6.长度受限的字符串追加strncat
1.追加count个字符从源字符串到目标空间的’\0’处;
2.若源字符串长度小于count,则只会追加源字符串过去,后面追加一个’\0’,与strncpy不同。
7.长度受限的字符串比较strncmp
直到比较出不同字符,或者count个字符比较完。
8.在一个字符串中寻找另一个字符串strstr
看strCharSet是不是string的一个子串;
找到则会返回string中目标字符串的地址,找不到返回NULL。
模拟实现strstr,代码如下:
char* my_strstr(const char* str1, const char* str2)
{
assert(str1 && str2);
const char* s1 = str1;
const char* s2 = str2;
const char* cur = str1;//用来存放匹配的起始地址
while (*cur)
{
s1 = cur;
s2 = str2;
while (*s1 && *s2 && (*s1 == *s2))//当s1和s2相等且都不为\0
{
s1++;
s2++;
}
if (*s2 == '\0')//s2找完,返回匹配地址
{
return cur;
}
cur++;
}
return NULL;
}
9.内存拷贝memcpy
1.memcpy函数从src指向的内存单元拷贝count个字节的数据到dest指向的内存空间;
2.遇到’\0’不会停下来;
3.dest和src不能有重叠;
模拟实现memcpy,代码如下:
void* my_memcpy(void* dst, const void* src, size_t count)
{
assert(dst && src);
void* ret = dst;
while (count--)
{
*((char*)dst) = *((char*)src);
dst = (char*)dst + 1;//由于dst是void*类型的,不能直接运算,要先强转为char*类型
src = (char*)src + 1;
}
return ret;
}
10.可实现重叠的内存拷贝memmove
它与memcpy的区别就是,memmove可以实现重叠空间的内存拷贝。
模拟实现memmove,代码如下:
void* my_memmove(void* dst, const void* src, size_t count)
{
assert(dst && src);
void* ret = dst;
if (dst < src)//源地址在后, 前 -> 后
{
while (count--)
{
*((char*)dst) = *((char*)src);
dst = (char*)dst + 1;
src = (char*)src + 1;
}
}
else//源地址在前, 后 -> 前
{
while (count--)
{
*((char*)dst + count) = *((char*)src + count);
}
}
return ret;
}
11.内存比较memcmp
比较从buf1和buf2开始的count个字节的数据,逐个字节进行比较。
12.内存设置memset
向dest所指向的空间设置count个字节的c字符。