C语言一文复习重点难点

一、指针和数组

1.什么是指针:

  1. 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。
  2. 指针的大小是固定的4/8个字节(32位平台/64位平台)。
  3. 指针是有类型,指针的类型决定了指针的±整数的步长,指针解引用操作的时候的权限。

2.什么是指针数组?什么是数组指针?什么是函数指针?

int* p[] 		//指针数组
int(*p)[]		//数组指针
void(*p)(int x,int y)	//函数指针

3.程序的结果是什么?(含答案)

1.

int main()
{
    
    
    int a[5] = {
    
     1, 2, 3, 4, 5 };
    int *ptr = (int *)(&a + 1);
    printf( "%d,%d", *(a + 1), *(ptr - 1));
    return 0; 
}

(a + 1)等同于a[1],第一个是4,a的类型是int [5],&a的类型就是int()[5],是个数组指针。所以给int(*)[5]类型加一,相当于加了一个int [5]的长度。也就是这个指针直接跳过了a全部的元素,直接指在了刚好越界的位置上,然后转换成了int *后再减一,相当于从那个位置向前走了一个int,从刚好越觉得位置回到了1的地址处,所以第二个是1。
答:4,1

2.

struct Test
{
    
    
 int Num;
 char *pcName;
 short sDate;
 char cha[2];
 short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
int main()
{
    
    
 printf("%p\n", p + 0x1);
 printf("%p\n", (unsigned long)p + 0x1);
 printf("%p\n", (unsigned int*)p + 0x1);
 return 0; }

第一行:20的16进制是14,14+0 = 14
第二行:强转long,1+0 = 1
第三行:强转指针:4/8+0 = 4/8
在这里插入图片描述

3.

int main()
{
    
    
    int a[4] = {
    
     1, 2, 3, 4 };
    int *ptr1 = (int *)(&a + 1);
    int *ptr2 = (int *)((int)a + 1);
    printf( "%x,%x", ptr1[-1], *ptr2);
    return 0; }

答:4,2.

4.

#include <stdio.h>
int main()
{
    
    
    int a[3][2] = {
    
     (0, 1), (2, 3), (4, 5) };
    int *p;
    p = a[0];
    printf( "%d", p[0]);
 return 0;
}

请添加图片描述
逗号表达式,只存右边第一个数,其余补0,所以输出1

5.

int main()
{
    
    
	int aa[2][5] = {
    
     1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int* ptr1 = (int*)(&aa + 1);
	int* ptr2 = (int*)(*(aa + 1));
	printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
	return 0;
}

1的地址+整个数组的地址-1 ->10的地址:10
aa+1 指向二维数组第二行第一个6,输出:10,5

6.

int main()
{
    
    
 char *a[] = {
    
    "work","at","alibaba"};
 char**pa = a;
 pa++;
 printf("%s\n", *pa);
 return 0; }

在这里插入图片描述
pa++后指向“at”

7.

int main()
{
    
    
	const char* c[] = {
    
     "ENTER","NEW","POINT","FIRST" };
	const char** cp[] = {
    
     c + 3,c + 2,c + 1,c };//逆置"FIRST","POINT","NEW","ENTER"
	const char*** cpp = cp;
	printf("%s\n", **++cpp);//"POINT"
	printf("%s\n", *-- * ++cpp + 3);//"ENTER" 从第三个开始er
	printf("%s\n", *cpp[-2] + 3);//"FIRST" 从第三个开始 st
	printf("%s\n", cpp[-1][-1] + 1);//"NEW" 从第一个开始EW
	return 0;
}

在这里插入图片描述

二、结构体

结构是一些值的集合,这些值称为成员变量结构的每个成员可以是不同类型的变量。
如:

struct Stu
{
    
    
 char name[20];//名字
 int age;//年龄
 char sex[5];//性别
 char id[20];//学号
}

1.结构体、联合、枚举体他们之间区别

联合也是一种特殊的自定义类型,这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫共用体)。
联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)
联合体内存取最大值并对齐

2.内存对齐

内存对齐的规则+如何计算

按最大的内存对齐,小的放在一起,不够的补齐。

eg1:

struct S1
	{
    
    
		char c1;//2
		int i;//4
		char c2;//2
	};
	printf("%d\n", sizeof(struct S1));

第一行、第三行:2补齐为4,所以输出12.

eg2:

struct S2
	{
    
    
		char c1;
		char c2;
		int i;
	};
	printf("%d\n", sizeof(struct S2));

一二行凑够4,所以输出8

结构体嵌套

struct S3
{
    
    
 double d;
 char c;
 int i;
};
printf("%d\n", sizeof(struct S3));

struct S4
{
    
    
 char c1;
 struct S3 s3;
 double d;
};
printf("%d\n", sizeof(struct S4);
)

struct s3是16,此时s4嵌套了s3,但是依旧是以s3 的double d为准对齐,所以char c1;补齐为8,struct S3 s3;,2*8 = 16,double d为8 。答案是32.

为什么要对齐:

如果不对齐的话,一个变量就会被分到2个(或多个)内存空间。
在这里插入图片描述
性能原因:为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

三、库函数

1.常见的库函数的功能及使用

2.模拟实现常见库函数

四、关键字

1.const

2.static

五、其他

1.什么是大小端?如何判断大小端?

2.malloc和calloc和realloc的区别

malloc:向内存申请一块连续可用的空间,并返回指向这块空间的指针。
calloc:会在返回地址之前把申请的空间的每个字节初始化为全0。
realloc:对动态开辟内存大小的调整。(增大或缩小)

猜你喜欢

转载自blog.csdn.net/kris_paul/article/details/119827217