1.内存管理
2. 结构体内存对其规则
#pragma pack(N) 每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中的n就是你要指定的“对齐系数”。
如果没有通过宏,那么在32位Linux主机上默认指定对齐值为4,64位的默认对齐值为8,AMR CPU默认指定对齐值为8;
#include <stdio.h>
#include <string.h>
int main() {
char str1[] = "abcd";
char str2[] = {'a','b','c','d','\0'};
char *str3 = "abcd"; //这样的话,*str3就相当于str1[] str3也就数组名
//上述三个是相同的,str2最后一个一定要加'\0'
//str1,str2,str3都可以理解为数组名(也就是数组的首元素地址)
//str1和str2都可以通过下标的方式改变对应的值
//str3的方式,是按照常量的方式看待str3的,不能通过下标的方式修改
/*
* 一般情况下,数组名表示数组首元素地址
* 特殊情况:
* sizeof(数组名),此时的数组名表示整个数组
* &数组名,此时表示整个数组的地址
*/
// sizeof用来是按照字节数的(实际占用内存长度),字符、字符串、'\0'整形都能计算
// sizeof(地址)就是等于一个地址类型占用的字节大小,跟指向的类型无关。
// strlen用来字符数的长度,遇到'\0'就会停止计算长度。只能计算字符数组(以\0结尾)
// strlen(地址)从这个地址开始计算,一直计算到\0为止。
//字符串数组
char week[3][10] = {
"Monday",
"Thenday",
"Wenday"
};
char *pweek[]{ //char型指针数组
"Monday",
"Thenday",
"Wenday"
};
//一维数组
int a[] = {1,2,3,4,5,6};
int *p = a;
printf("%d\n",*(p+1));
//指针数组
int x = 1, y = 2, z = 3;
int* b[3] = { &x,&y,&z }; //每一个元素都是指针的数组
int** pb = b; //pb和b可以互换
for (int i = 0; i < 3; i++) {
printf("%d\n", **(b + i));
}
for (int i = 0; i < 3; i++) {
printf("%d\n", *(pb[i]));
}
//二维数组+数组指针
int array[3][4]={
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
int (*pa)[4] = array; //pa和array可以互换
//pa\array是第一行一维数组的地址
//pa[0]\array[0]是第一行一维数组的首元素的地址
//pa[0] pa[1]...可以理解为每一行一维数组的数组名字
//pa+0 pa+1 ...和上边等价
/而pa[0]+1 不等于 pa+1
for (int i = 0;i < 3;i++){
for (int j = 0; j < 4; j++){
printf("%d ",*(*(pa+i)+j));
}
printf("\n");
}
for (int i = 0;i < 3;i++){
for (int j = 0; j < 4; j++){
printf("%d ",*(array[i]+j));
}
printf("\n");
}
return 0;
}
3. 字符串函数
复制字符串
strcpy(str1,str2) str1的位置必须够,但是不检查是否位置够
strncpy(str1,str2,n) 按照n的个数复制字符 该函数不会自己添加’\0’ 如果没有的话,需要自己添加
拼接字符串
strcat(str1,str2) str1的位置必须够,但是不检查是否位置够 该函数不会自己添加’\0’
strncat(str1,str2,n) 按照n的个数拼接字符 该函数自动添加空字符\0
strncat(
str1,
str2,
sizeof(str1) - strlen(str1) - 1
);
比较字符
strcmp(str1,str2)
strncmp(str1,str2,n)
字符串拼接
sprintf(),snprintf()
char first[6] = "hello";
char last[6] = "world";
char s[40]; //s接收
sprintf(s, "%s %s", first, last);
4. 二维数组
#include<stdio.h>
int main(void)
{
int array[3][4] = {
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
for (int i = 0; i < 3; i++)
{
printf("%d %d %d %d\n", array[i][0], array[i][1], array[i][2], array[i][3]);
}
for (int i = 0; i < 3; i++)
{
printf("%p %p %p %p\n", &array[i][0], &array[i][1], &array[i][2], &array[i][3]);
}
printf("在理解的时候,[ ]就相当于*解引用;若有[ ]又有&就相当于这两个都没有\n");
printf("二维数组名字直接使用表示数组指针 若解一层引用表示到具体的某一行数组名\n");
printf("array: %p *array: %p\n", array, *array);
printf("array + 1: %p *array + 1: %p\n", array + 1, *array + 1);
printf("&array[0]: %p array[0]: %p\n", &array[0], array[0]);
printf("&array[0] + 1:%p array[0] + 1:%p\n", &array[0] + 1, array[0] + 1);
int(*p1)[4];
int(*p2)[4];
int(*p3)[4];
p1 = array; //用指针数组表示二维数组的最佳表示方法
p2 = *array; //不会报错,但是逻辑上别扭
p3 = array[0]; //不会报错,但是逻辑上别扭
printf("%p %p %p\n", p1 + 1, p2 + 1, p3 + 1);
printf("%p %p %p\n", *(p1 + 1) + 2, *(p2 + 1) + 2, *(p3 + 1) + 2);
int(*p4)[4];
p4 = array[0] + 1; //这样虽然不会报错,但是逻辑错误
printf("%p\n", p4 + 1); //错误示例
//正确示范
p4 = array + 1;
printf("%p\n", *p4 + 1); //这样的话,逻辑是正确的
return 0;
}
5. const 指针
6. 字符串
#define DMG "I am ueueq"
int main(void)
{
char str1[] = { 'A','B','C','D','E','\0' };
char str2[] = "ABCDE";
char* str3 = "ABCDE";
//strlen表示的是字符串的实际长度,遇到‘\0’停止,且不包括‘\0’
//sizeof表示实际占用内存大小,包括'\0'
printf("strlen:%d sizeof:%d\n", strlen(str1), sizeof(str1));
printf("strlen:%d sizeof:%d\n", strlen(str2), sizeof(str2));
printf("str2:%p *str3%p\n", str2, str3);
str1[1] = 'Z';
str2[1] = 'Z';
// str3[1] = 'Z'; //字面量的字符串定义方法,属于常量定义,不能通过数组下标的方式改变字符串
puts(str1);
puts(str2);
puts(str3);
//测试新的示例
//数组与指针定义字符串的不同
/*
字面量的定义方式,会将字符串存储在静态存储区(文本);
若采用数组的定义方式,还会复制一份到到内存地址中,即str所指的位置;并且str所指向的位置不能改变,只能str+1,不能++str
若采用指针的定义方式,会直接将静态存储区的地址放到strp。可以++strp指向第二个字符;这种方式感觉就是字符指针。
*/
/*
C语言中定义的相同的字符串(字面量方式)。可能只存储一份。
*/
char str[] = DMG;
char* strp = DMG;
printf("str[]:%p *strp:%p\n", str, strp);
printf("DMG:%p\n", DMG);
const int* pt;
int const* pz;
int* const pl;
return 0;
}
7. 图片记录
8. 函数指针
void func(int a, int b); //函数声明
void (*pf)(int, int); //函数指针定义
pf = func; //赋值
pf(1, 2); //函数指针使用
int func(char*, int);
int (*pf)(char*, int);
pf = func;
pf('0', 1);
//函数指针数组
int func(char*);
int (*pf[10])(char*); //表示每一个元素都是指向func函数的函数指针