(C语言进阶)笔试题详解

一.要点回顾

1.一维整形数组 

(1)sizeof()对一维整形数组的应用

#include
int main()
{
    int a[] = {1,2,3,4};
    printf("%d\n", sizeof(a));//16
//sizeof(数组名),数组名表示整个数组,计算的是整个数组的大小,单位是字节
    printf("%d\n", sizeof(a+0));//  4/8
//a不是单独放在sizeof内部,也没有取地址,所以a就是首元素的地址,故a+0也是首元素的地址
//地址的大小为4/8个字节
    printf("%d\n", sizeof(*a));//4
//*a中的a是数组中首元素的地址,*a就是对首元素的地址解引用,找到的就是首元素
//首元素的大小为4个字节
    printf("%d\n", sizeof(a+1));//  4/8
//这里的a是数组首元素的地址,a+1为第二个元素的地址
//sizeof(a+1)就是地址的大小
    printf("%d\n", sizeof(a[1])); //4
//                sizeof(*(a+1));
//计算的是第二个元素的大小
    printf("%d\n", sizeof(&a)); // 4/8
//&a取出的是整个数组的地址,计算的也是地址
    printf("%d\n", sizeof(*&a));//16
//&a---->int(*)[4]
//&a拿到的是整个数组的地址,解引用后获得整个数组的元素
//故求的是整个数组所占内存的大小
    printf("%d\n", sizeof(&a+1));//  4/8
//&a拿到的是整个数组的地址,+1后跳过一整个数组的大小(16个字节)
//&a+1也是地址,故为4/8个字节
    printf("%d\n", sizeof(&a[0]));//   4/8
//                   sizeof(&*(a+0))
//a[0]是第一个数组元素,取地址后得到的是第一个元素的地址
    printf("%d\n", sizeof(&a[0]+1)); //  4/8
//&a[0]是数组首元素的地址,+1后得到第二个元素的地址
    return 0;
}

2.一维字符型数组 

(1) sizeof()对一维字符型数组的应用

#include
int main()
{
    char arr[] = { 'a','b','c','d','e','f'};
    printf("%d\n", sizeof(arr));//6
//sizeof(数组名),数组名表示整个数组,计算的是整个数组的大小,单位是字节
    printf("%d\n", sizeof(arr+0));//  4/8
//arr+0是数组首元素的地址
    printf("%d\n", sizeof(*arr));//1
//*arr是数组的首元素,大小为1字节
    printf("%d\n", sizeof(arr[1]));//1
//                  sizeof(*(arr+1))
//为数组的第二个元素
    printf("%d\n", sizeof(&arr));//  4/8
//&arr取出的是整个数组的地址,是地址就是4/8个字节
    printf("%d\n", sizeof(&arr+1)); //  4/8
//&arr+1也是地址,故为4/8个字节
    printf("%d\n", sizeof(&arr[0]+1));// 4/8
//&arr[0]是数组首元素的地址,+1后得到第二个元素的地址
    return 0;
}

(2)strlen()函数对一维字符型数组的应用 

#include
#include
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", strlen(arr));//随机值
	//strlen函数从指定地址进入后,需要遇到\0才会停止计数
	//字符数组中没有\0,故其会一直向后读取,直到在内存中遇到\0
	printf("%d\n", strlen(arr + 0));//随机值
	//arr+0表示的是数组的首元素地址
	printf("%d\n", strlen(*arr));//错误
	//*arr表示的是数组的首元素'a'
	//strlen需要的参数为指针类型,报错
	printf("%d\n", strlen(arr[1]));//错误
	//arr[1]表示数组的首元素
	//strlen需要的参数为指针类型,报错
	printf("%d\n", strlen(&arr));//随机值
	//&arr取出的是整个数组的地址,而整个数组地址的起始点为首元素地址
	printf("%d\n", strlen(&arr + 1));//随机值-6
	//&arr拿到的是整个数组的地址,+1后跳过一整个数组的大小(6个字节)
	printf("%d\n", strlen(&arr[0] + 1));//随机值-1
	//&arr[0]是数组首元素的地址,+1后得到第二个元素的地址
	return 0;
}

3.字符串 

(1)sizeof()对字符串的应用

#include    
int main()
{
	char arr[] = "abcdef";
	//[a b c d e f \0]
	printf("%d\n", sizeof(arr));  //7
//arr在sizeof函数中表示全部元素,\0也会计数
	printf("%d\n", sizeof(arr+0));  //  4/8
//第一个元素的地址
	printf("%d\n", sizeof(*arr));  //1
//第一个元素
	printf("%d\n", sizeof(arr[1]));  //1
//第二个元素
	printf("%d\n", sizeof(&arr));  //  4/8
//整个字符串的地址
	printf("%d\n", sizeof(&arr+1));//  4/8
//从首元素地址跳过一整个字符串长度的地址
	printf("%d\n", sizeof(&arr[0]+1)); //  4/8
//第二个元素的地址
	return 0;
}

(2)strlen()对字符串的应用

#include    
#include
int main()
{
	char arr[] = "abcdef";
	//[a b c d e f \0]
	printf("%d\n", strlen(arr));  //6
	//首元素地址
	printf("%d\n", strlen(arr+0)); //6
	//首元素地址
	printf("%d\n", strlen(*arr)); //错误
	//strlen需要的参数为指针类型,报错
	printf("%d\n", strlen(arr[1]));  //错误
	//strlen需要的参数为指针类型,报错
	printf("%d\n", strlen(&arr));  //6
	//首元素地址
	printf("%d\n", strlen(&arr+1));  //随机值
	//首元素地址跳过一整个字符串长度的地址
	printf("%d\n", strlen(&arr[0]+1));  //5
	//第二个元素的地址
	return 0;
}

4.字符型指针 

(1)sizeof()对字符型指针的应用 

#include
int main()
{
	char* p = "abcdef";
	printf("%d\n", sizeof(p));//  4/8
	//p是字符串的首元素地址
	printf("%d\n", sizeof(p+1));// 4/8
	//第二个元素的地址
	printf("%d\n", sizeof(*p));// 1
	//字符串首元素
	printf("%d\n", sizeof(p[0]));// 1
	//字符串首元素
	printf("%d\n", sizeof(&p));// 4/8
	//指向首元素地址的二级指针
	printf("%d\n", sizeof(&p+1));//  4/8
	//指向第二个元素地址的二级指针
	printf("%d\n", sizeof(&p[0]+1));//  4/8
	//             sizeof(&(*(p+0))+1)
	//第二个元素的地址
	return 0;
}

(2)strlen()对字符型指针的应用

#include
#include
int main()
{
	char* p = "abcdef";
	printf("%d\n", strlen(p)); //6
//第一个元素的地址
	printf("%d\n", strlen(p+1));//5
//第二个元素的地址
	printf("%d\n", strlen(*p));//报错
//第一个元素,与strlen所需的参数不同
	printf("%d\n", strlen(p[0]));//报错
//第一个元素,与strlen所需的参数不同
	printf("%d\n", strlen(&p));//随机值1
//整个字符串的地址
	printf("%d\n", strlen(&p+1));//随机值2
//首个元素地址+整个字符串长度的地址
	printf("%d\n", strlen(&p[0]+1)); //5
//第二个元素的地址
	return 0;
}

5.二维整形数组

(1) sizeof()对二维整形数组的应用

#include
int main()
{
	int a[3][4] = {0};
	printf("%d\n", sizeof(a));//48
//a在sizeof中表示整个数组元素所占的内存大小
	printf("%d\n", sizeof(a[0][0]));//4
//第一个元素
	printf("%d\n", sizeof(a[0]));//16
//第一行元素
	printf("%d\n", sizeof(a[0]+1));//  4/8
//第一行第二个元素的地址
	printf("%d\n", sizeof(*(a[0]+1)));//4
//第一行第二个元素
	printf("%d\n", sizeof(a+1));//  4/8
//第二行元素的地址
	printf("%d\n", sizeof(*(a+1)));//16
//第一行元素
	printf("%d\n", sizeof(&a[0]+1));//  4/8
//第二行元素的地址
	printf("%d\n", sizeof(*(&a[0]+1)));//16
//第二行元素
	printf("%d\n", sizeof(*a));//16
//第一行元素
	printf("%d\n", sizeof(a[3]));//16
//第三行元素
	return 0;
}

 二.笔试题

 1.第一题

题目: 

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

解析:

答案:2,5

#include
int main()
{
    int a[5] = {1,2,3,4,5};
    int* ptr = (int*)(&a+1);
    //ptr为首元素地址跳过整个数组
    printf("%d,%d",*(a+1),*(ptr-1));//2,5
    return 0;
}

(C语言进阶)笔试题详解_第1张图片

2.第二题 

题目: 

#include
//已知结构体Test类型的变量大小为20个字节
struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p=(struct Test*)0x100000;
int main()
{
	printf("%p\n",p+0x1);  //0x100014
	//struct Test类型加一增加20个字节
	printf("%p\n", (unsigned long)p + 0x1);//0x100001
	//unsigned long类型加一增加1个字节
	printf("%p\n", (unsigned int*)p + 0x1);//0x100004
	//unsigned int*类型加一增加4个字节
	return 0;
}

解析:

答案: 0000000000100020 ,0000000000100001  , 0000000000100004

#include
//已知结构体Test类型的变量大小为20个字节
struct Test
{
    int Num;
    char* pcName;
    short sDate;
    char cha[2];
    short sBa[4];
}*p=(struct Test*)0x100000;
int main()
{
    printf("%p\n",p+0x1);  //0x100014
    //struct Test类型加一增加20个字节
    printf("%p\n", (unsigned long)p + 0x1);//0x100001
    //unsigned long类型加一增加1个字节
    printf("%p\n", (unsigned int*)p + 0x1);//0x100004
    //unsigned int*类型加一增加4个字节
    return 0;
}

3.第三题 

题目: 

#include
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,20000

 #include
int main()
{
    int a[4] = {1,2,3,4};
    int* ptr1 = (int*)(&a + 1);
    //ptr1为数组首元素地址跳过一整个数组的地址
    int* ptr2 = (int*)((int)a + 1);
    //(int)a+1增加一个字节,(int*)((int)a + 1)为首元素地址向后一个字节
//00 00 00 01 | 00 00 00 02 | 00 00 00 03 | 00 00 00 04——数组中元素地址
//01 00 00 00 | 02 00 00 00 | 03 00 00 00 | 04 00 00 00——在内存中存储(小端存储)
//  |                                                  |
// ptr2                                               ptr1
    printf("%x,%x",ptr1[-1],*ptr2);
//以十六进制输出时,ptr1[-1]为后退四个字节,然后读取四个字节输出——00 00 00 04
//*ptr2为读取四个字节然后输出——02 00 00 00
    return 0;
}

(C语言进阶)笔试题详解_第2张图片

4.第四题 

题目: 

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

 解析:

答案:1

#include
int main()
{
    int a[3][2] = {(0,1),(2,3),(4,5)};//逗号表达式,读取的值为后面的数
    int* p;
    p = a[0];
    //p为第一行的元素 
    printf("%d",p[0]);
    //p[0]是第一行的第一个元素
    return 0;
}

 (C语言进阶)笔试题详解_第3张图片

 5.第五题

题目: 

#include
int main()
{
	int a[5][5];
	int(*p)[4];
	p = a;
	printf("%p,%d\n",&p[4][2]-&a[4][2], &p[4][2] - &a[4][2]);
	return 0;
}

 解析:

答案: -4,FFFFFFFC

#include
int main()
{
    int a[5][5];
    int(*p)[4];
    p = a;
    printf("%p,%d\n",&p[4][2]-&a[4][2], &p[4][2] - &a[4][2]);
//&p[4][2]-&a[4][2]=(-4)
//10000000 00000000 00000000 00000100——(-4)原码
//11111111 11111111 11111111 11111011——反码
//11111111 11111111 11111111 11111100——补码
//FF FF FF FC——十六进制
//按地址输出时把补码当做地址输出
    return 0;
}

(C语言进阶)笔试题详解_第4张图片

6.第六题 

 题目:

#include
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;
}

解析:

答案: 10,5

#include
int main()
{
    int aa[2][5] = {1,2,3,4,5,6,7,8,9,10};
    int* ptr1 = (int*)(&aa+1);
    //ptr1为首元素地址跳过整个数组后的地址
    int* ptr2 = (int*)(*(aa + 1));
    //          (int*)aa[1]
    printf("%d,%d",*(ptr1-1),*(ptr2-1)); //10,5
    //*(ptr1-1)—>*(a[2]-1)—>a[1][4]
    //*(ptr2-1))—>*(aa[1]-1)—>aa[0][4]
    return 0;
}

(C语言进阶)笔试题详解_第5张图片

7.第七题 

题目: 

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

解析:

答案:at 

#include
int main()
{
    char* a[] = {"work","at","alibaba"};
    char** pa = a;
    //pa为字符串首元素("work")的地址
    pa++;
    //++后pa指向"at"
    printf("%s\n",*pa);
    return 0;
}

8.第八题 

题目: 

#include
int main()
{
	char* c[] = {"ENTER","NEW","POINT","FIRST"};
	char** cp[] = {c+3,c+2,c+1,c};
	char*** cpp = cp;
	printf("%s\n", **++cpp);
	printf("%s\n", *--*++cpp+3);
	printf("%s\n", *cpp[-2]+3);
	printf("%s\n", cpp[-1][-1]+1);
	return 0;
}

解析:

答案: POINT,ER,ST,EW

#include
int main()
{
    char* c[] = {"ENTER","NEW","POINT","FIRST"};
    char** cp[] = {c+3,c+2,c+1,c};
    char*** cpp = cp;
    //cpp为c+3的地址


    printf("%s\n", **++cpp);//POINT
    //++cpp—>c+2的地址
    // **++cpp—>"POINT"的首元素地址

    printf("%s\n", *--*++cpp+3);//ER
    //cpp为c+2的地址
    //++cpp—>c+1的地址
    //--*++cpp—>c+1-1—>c
    //*--*++cpp—>"ENTER"的首元素地址
    //*--*++cpp+3—>"ENTER"第四个元素的地址

    printf("%s\n", *cpp[-2]+3);//ST
    //cpp为c+1的地址
    //cpp[-2]—>*(cpp-2)—>元素c+3—>"FIRST"的地址
    //*cpp[-2]+3—>*(cpp[-2]+3)—>"FIRST"的第四个元素的地址

    printf("%s\n", cpp[-1][-1]+1);//EW
    //cpp为c+1的地址
    //cpp[-1]—>*(cpp-1)—>元素c+2—>"POINT"的地址
    //cpp[-1][-1]—>*(cpp[-1]-1)—>"NEW"的地址
    //cpp[-1][-1]+1—>"NEW"第二个元素的地址
    return 0;
}

你可能感兴趣的:(算法,数据结构,c语言)