结构体
- 函数传递的时候,参数是需要压栈的。如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销会比较大。
- 结构体传参时,要传结构体的地址。
- 栈区:局部变量、函数的形式参数、函数调用也开辟空间
默认由高到低使用地址 - 堆区:动态内存分配、malloc/free,realloc,calloc
- 静态区:全局变量、静态变量
数据的存储
类型的意义:
- 使用这个类型开辟内存空间的大小(大小决定了适用范围)
- 决定了看待内存空间的视角(如:使用int和float存储相同数据内存数据会不一样)
数值计算
- 内存中用补码对整数数据进行存储
- 使用补码可以让减法更加方便(cpu只有加法器)
- 1-1
1+(-1)
//原码相加
00000000000000000000000000000001
10000000000000000000000000000001
10000000000000000000000000000010
//补码相加
00000000000000000000000000000001
11111111111111111111111111111111
00000000000000000000000000000000
大小端存储
- 大端模式,数据的地位保存在内存的高地址中,而数据的高位保存在内存的低地址中
- 小端模式,是指数据的低位保存在内存的低地址中,而数据的高位,保存在内存的高地址中
整形提升
#include<stdio.h>
int main()
{
char a=-1;
singned char b=-1;
unsigned char c=-1;
printf("a=%d,b=%d,c=%d",a,b,c);
return 0;
}//输出为-1,-1,255
- 对于char a=-1
在内存中a的数据为11111111;补码表示
由于打印数据为int则发生整形提升
char为有符号整型,则在a前面填充24个符号位数值1
得到(int)a内存数据为:11111111111111111111111111111111(此处依旧为补码)
将该补码同样的转换回原码时得到10000000000000000000000000000001即-1 - 对于singned char b=-1同上
- 对于unsigned char c=-1
与char a=-1类似
只是由于unsigned为无符号数,则在整形提升时填充24个0(无符号默认正数)
得到了(int)c内存数据为:0000000000000000000000011111111(补码)
计算原码得到255
浮点数
- 浮点数在计算机内存中的存储通常遵循IEEE 754标准。根据这个标准,一个浮点数通常由三部分组成:符号位、指数部分和尾数部分。
- 符号位:用于表示数的正负,占据一个比特位,0代表正数,1代表负数。
- 指数部分:用于表示数的阶码(指数),通常以偏移值的形式存储,这个偏移值可以确保指数可以表示负数。指数部分用来调整浮点数的数量级。
- 尾数部分:也称为尾数或尾数部分,用来存储浮点数的有效数字部分,决定了浮点数的精度。
- 单精度浮点数(32位)通常按照以下格式存储:
符号位(1位)
指数部分(8位)
尾数部分(23位) - 双精度浮点数(64位)通常按照以下格式存储:
符号位(1位)
指数部分(11位)
尾数部分(52位)
int main()
{
float f = 5.5;
//5.5
//101.1;二进制写法
//(-1)^0*1.011*2^2;IEEE 754写法
//S=0;符号位
//E=2;指数部分,此处加上偏移量127(2^7-1)为129即100000001
//M=1.011;尾数部分
//0 10000001 01100000000000000000000;内存存储数据
}
字符串与内存函数
字符串函数
strlen
- size_t strlen(const char * str);
- 字符串以’\0’作为结束标志,strlen函数返回的是在字符串中’\0’前面出现的字符个数 (不包含’\0’)。
- 参数指向的字符串必须要以\0’结束,
- 注意函数的返回值为siz_t,是无符号的
strcpy
- char* strcpy(char * destination,const char * source);
- 源字符串必须以’\0’结束。
- 会将源字符串中的’\0’拷贝到目标空间
- 目标空间必须足够大,以确保能存放源字符串
- 目标空间必须修改
strcat
- char * strcat(char * destination,const char* source)
- 源字符串必须以’\0’结束。
- 目标空间必须足够大,以确保能存放新字符串
- 目标空间必须修改
strcmp
- int strcmp(const char* str1,const char * str2)
- 第一个字符串大雨第二个字符串,返回大于0的数字
- 第一个字符串等于第二个字符串返回0
- 第一个字符串小于第二个字符串,返回小于0的数字
strstr
- char* strstr(const char * ,const char *);查找字符串
strtok
- char * strtok(char * str,const char * sep)
- sep参数是给字符串,定义了用作分隔符的字符集合
- 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符的标记
- strtok函数找到str中的下一个标记,并将其用\0结尾,返回一个指向这个标记的指针
- strtok函数的第一个参数部位NULL,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
- strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
- 如果字符串中不存在更多的标记,则返回NULL指针
内存函数
memcpy
- void * memcpy(void * destination,const void * source,size_t num)
- 函数memcpy从source的位置开始向后复制num个字节的数据到destionation的内存位置。
- 这个函数在遇到’\0’的时候并不会停下来
- 如果source和destination有任何的重叠,复制的结果都是未定义的
memmove
- void *memmove(void *dest, const void *src, size_t n);
- (能够处理内存重叠区域的复制类似memcpy)
memcpy
- int memcmp(const void *ptr1, const void *ptr2, size_t num);
- 按字节比较 ptr1 和 ptr2 所指向的内存区域的前 num 个字节。
- 如果两个内存区域在前 num 个字节上完全相同,则返回值为0;
- 如果不同,返回值为第一个不同字节的差值(ptr1 的字节值减去 ptr2 的字节值)。
memset
- void *memset(void *ptr, int value, size_t num);
- 用于设置一块内存区域的值
- 注意此处num表示为字节数
注意上述函数中的修改区域是按某数据类型还是字节划分
#include <stdio.h>
#include <string.h>
int main() {
int arr[5]={0};
memset(arr, 1, sizeof(arr));
return 0;
}
//会使得arr内存空间为(0x)01 01 01 01 01 01 01 01 01 01...