潜学C语言——指针相关题目

 题目一:


int main()
{	//数组名是首元素的地址
	//1.sizeof(数组名) - 数组名表示整个数组
	//2.&数组名 - 数组名表示整个数组
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(a + 0));
	printf("%d\n", sizeof(*a));
	printf("%d\n", sizeof(a + 1));
	printf("%d\n", sizeof(a[1]));
	printf("%d\n", sizeof(&a));
	printf("%d\n", sizeof(*&a));
	printf("%d\n", sizeof(&a + 1));
	printf("%d\n", sizeof(&a[0]));
	printf("%d\n", sizeof(&a[0]+1));
	return 0;
}

 

int main()
{	//数组名是首元素的地址
	//1.sizeof(数组名) - 数组名表示整个数组
	//2.&数组名 - 数组名表示整个数组
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));//sizeof(数组名) - 计算的是数组总大小 - 单位是字节 - 16
	printf("%d\n", sizeof(a + 0));//4 - 数组名这里表示首元素地址,a+0还是首元素地址,地址大小就是4/8个字节
	printf("%d\n", sizeof(*a));//4 - 数组名表示首元素地址,*a就是首元素,sizeof(*a)就是4
	printf("%d\n", sizeof(a + 1));//4 - 数组名这里表示首元素地址,a+1是第二个元素的地址,地址的大小就是4/8个字节
	printf("%d\n", sizeof(a[1]));//4 - 第二个元素的大小
	printf("%d\n", sizeof(&a));//4 &a取出的是数组的地址,但是数组的地址也是地址,地址的大小就是4/8个字节
	printf("%d\n", sizeof(*&a));//16 - &a是数组的地址,数组的地址解引用访问数组,sizeof计算的就是数组的大小,单位是字节
	printf("%d\n", sizeof(&a + 1));//4/8 &a是数组的地址,&a+1虽然地址跳过整个数组,但还是地址
	printf("%d\n", sizeof(&a[0]));//4/8 &a[0]是第一个元素的地址
	printf("%d\n", sizeof(&a[0]+1));//4/8 第二个元素的地址
	return 0;
}

题目二: 

//字符数组
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr));// 6 sizeof计算的是数组大小 6*1=6
printf("%d\n", sizeof(arr + 0));//4/8 arr是首元素的地址,arr+0还是首元素的地址 地址的大小是4/8字节
printf("%d\n", sizeof(*arr));//1 arr是首元素地址,*arr是首元素,首元素是字符,大小是一个字节
printf("%d\n", sizeof(arr[1]));//1
printf("%d\n", sizeof(&arr));//4 &arr虽然是数组的地址,但还是地址,地址的大小是4/8个字节 
printf("%d\n", sizeof(&arr + 1));//4 &arr+1是跳过整个数组后的地址,地址大小是4/8个字节
printf("%d\n", sizeof(&arr[0] + 1));//4 第二个元素的地址

题目三: 

char arr[] = { 'a','b','c','d','e','f' };

printf("%d\n", strlen(arr));//随机值 \0的位置不确定
printf("%d\n", strlen(arr + 0));//随机值 
printf("%d\n", strlen(*arr));//err
printf("%d\n", strlen(arr[1]));//err
printf("%d\n", strlen(&arr));//随机
printf("%d\n", strlen(&arr + 1));//随机值
printf("%d\n", strlen(&arr[0] + 1));//随机

题目四:

int main()
{
	char arr[] = "abcdef";

	printf("%d\n", sizeof(arr));//7  a b c d e f \0 7个字符 7*1=7 sizeof计算的数组的大小。单位是字节
	printf("%d\n", sizeof(arr + 0));//4/8计算的是地址的大小 arr+0是首元素的地址
	printf("%d\n", sizeof(*arr));//1 *arr是首元素,sizeof(*arr)计算首元素大小
	printf("%d\n", sizeof(arr[1]));//1 arr[1]是第二个元素,sizeof(arr[1])计算的是第二个元素的大小
	printf("%d\n", sizeof(&arr));//4  &arr虽然是数组的地址,但也是地址,所以是4/8个字节
	printf("%d\n", sizeof(&arr + 1));//4/8  &arr+1是跳过整个数组后的地址,但也是地址
	printf("%d\n", sizeof(&arr[0] + 1));// 4/8 &arr[0]+1 第二个元素的地址


	return 0;
}

数组名是首元素的地址,&和sizeof数组名除外

只有 sizeof(数组名)  的时候,计算的是整个数组的大小,这后面+0,就不是 “纯净的”  sizeof(数组名) 了,换句话说只有 sizeof(数组名)   这种特定的形式才是数组大小

 

题目五: 

int main()
{
	char arr[] = "abcdef";

	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr + 0));
	printf("%d\n", strlen(*arr));
	printf("%d\n", strlen(arr[1]));
	printf("%d\n", strlen(&arr));
	printf("%d\n", strlen(&arr + 1));
	printf("%d\n", strlen(&arr[0] + 1));
	return 0;
}

//6 \0之前出现了6个 

//6 理由同上

//err

//err

// 6 &arr - 数组的地址 - 数组指针 char(*p)[7]=&arr

//随机值

//5 从b的位置开始数字符

题目六: 

int main()
{
	char* p = "abcdef";

	printf("%d\n", sizeof(p));
	printf("%d\n", sizeof(p + 1)); 
	printf("%d\n", sizeof(*p));
	printf("%d\n", sizeof(p[0]));
	printf("%d\n", sizeof(&p));
	printf("%d\n", sizeof(&p + 1));
	printf("%d\n", sizeof(&p[0] + 1));
	return 0;
}

// 4/8 - p + 1得到的是字符b的地址

//4/8 - 计算指针变量p的大小

//1 *p就是字符串的第一个字符 - 'a'

//1  int arr[10]; arr[0] == *(arr+0)   p[0] == *(p+0) == 'a'

//4/8 地址

//4/8 地址

//4/8 地址

题目七:


int main()
{
	char* p = "abcdef";

	printf("%d\n", strlen(p));
	printf("%d\n", strlen(p + 1)); 
	printf("%d\n", strlen(*p));
	printf("%d\n", strlen(p[0]));
	printf("%d\n", strlen(&p));
	printf("%d\n", strlen(&p + 1));
	printf("%d\n", strlen(&p[0] + 1));

	return 0;
}

 //6

//5

//err

//err

//随机值

// 随机值

//5

 题目八:

//二维数组
int main()
{
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(a[0][0]));
	printf("%d\n", sizeof(a[0]));
	printf("%d\n", sizeof(a[0]+1));
	printf("%d\n", sizeof(*(a[0] + 1));
	printf("%d\n", sizeof(a + 1));
	printf("%d\n", sizeof(*(a + 1));
	printf("%d\n", sizeof(&a[0] + 1));
	printf("%d\n", sizeof(*(&a[0] + 1));
	printf("%d\n", sizeof(*a));
	printf("%d\n", sizeof(a[3]));

	return 0;
}

//48 3*4*4

//4

//16 4*4 a[0]相当于第一行作为一维数组的数组名,sizeof(arr[0])把数组名单独放在sizeof()内,计算的是第一行的大小 

// 4 - a[0]是第一行的数组名,数组名此时是首元素的地址,a[0]其实就是第一昂第一个元素的地址,所以a[0] + 1就是第一行第二个元素的地址,地址大小是4/8个字节

//4 - *(a[0] + 1) 是第一行第二个元素,大小是4字节

//4 a是二维数组的数组名,没有sizeof(数组名),也没有&(数组名),所以a是首元素地址  而把二维数组看成一维数组时,二维数组的首元素是他的第一行,a就是第一行(首元素)的地址    //a+1就是第二行的地址

//16 sizeof(a[1]) 计算第二行的大小,单位是字节

//4 第二行的地址 

//16 计算第二行大小

//a是首元素地址,就是第一行的地址 sizeof(*a)就是计算第一行的大小

//16

总结:

1.sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小

2.&数组名,这里的数组名表示整个数组,取出的是整个数组的地址

3.除此之外所有的数组名都表示首元素的地址

指针笔试题:

题目一:

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

题目二:

struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}* p;
//假设p的值为0x100000,如下表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节

int main()
{
	 p = (struct Test*)0x100000;
	printf("%p\n", p + 0x1);
	printf("%p\n",(unsigned long) p + 0x1);
	printf("%p\n", (unsigned int*)p + 0x1);

	return 0;
}

解析:

指针加减整数的计算,取决于指针类型

答案: 0x00100014  0x00100001  0x00100004

题目三:

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

ptr1[-1] = ptr+(-1)

答案:4  2000000

题目四:

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)结果为1,(2,3)结果为3,(4,5)结果为5

 后几位自动用0补齐

 答案:1

题目五:

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

解析:

p[4][2] = (*(p + 4) + 2)

+4 — 跳过4个整型 

地址 - 地址 = 两个地址之间的元素个数

答案:FFFFFFFC   -4

题目六:

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\n", *(ptr1 - 1), *(ptr2 - 1));
	return 0;

}

解析:

aa[1] - 第二行首元素地址

答案:10,5

几个相等的表达方式:

	int arr[10] = { 1,2,3,4,5 };
	int* p = arr;
	*(p + 2) == p[2] == * (arr + 2) == arr[2]

题目七:

int main()
{
	char* a[] = { "work","at","alibaba" };
	char** pa = a;

	pa++;
	printf("%s\n", *pa);
	return 0;
}

解析:

char* p = "abcdef";//字符指针,把常量字符串首字符的地址a放到p中

pa++指向第二个元素

答案:at

题目八:

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

解析:

printf中的++是真实存在的(前后有关联关系,cpp在+的时候在发生变化)

*cpp[-2]+3 == * *(cpp+(-2)) +3

cpp[-1][-1]+1 == *( *(cpp-1) -1 ) +1

答案:POINT, ER, ST, EW

题目九:

int main()
{
	unsigned long pulArray[] = { 6,7,8,9,10 };
	unsigned long* pulPtr;
	pulPtr = pulArray;
	*(pulPtr + 3) += 3;
	printf("%d,%d\n", *pulPtr, *(pulPtr + 3));
	return 0;
}

答案:6,12

题目十:

下面关于指针运算说法镇古鳄的是:()

A.整型指针+1,指针偏移一个字节

B.指针-指针得到的是指针与指针的字节个数

C.整型指针解引用操作访问四个字节

D.指针不能比较大小

答案:C

解析:

A.指针偏移一个整型大小

B.得到的是指针与指针之间的元素个数

D.指针可以比较大小

题目十一:

写一个函数,可以逆序一个字符串的内容

#include<string.h>
#include<assert.h>
void reverse(char* str)
{
	assert(str);
	int len = strlen(str);
	char* left = str;
	char* right = str + len - 1;

	while (left<right)
	{
		char tmp = *left;
		*left = *right;
		*right = tmp;
		left++;
		right--;
	}
}
int main()
{
	char arr[256] = { 0 };
	scanf("%s", arr);//abcdef --->fedcba
	//逆序函数
	reverse(arr);
	printf("%s\n", arr);
	return 0;
}

 题目十二:

求0-100000之间的所有水仙花数并输出

#include<math.h>
int main()
{
	int i = 0;
	for (i = 0; i <= 100000; i++)
	{
		//判断i是否为水仙花数(自幂数)
		//1.计算i的位数 - n位数
		int n = 1;
		int tmp = i;
		int sum = 0;
		while (tmp /= 10)
		{
			n++;
		}
		//123/10 n++
		//12/10 n++
		//1/10
		tmp = i;
		while (tmp)
		{
			sum += pow(tmp % 10, n);
			tmp /= 10;
		}
		//3.比较i == sum
		if (i == sum)
		{
			printf("%d ", i);
		}
	}

	return 0;
}

题目十三:打印菱形

int main()
{
    int line = 0;
    scanf("%d", &line);
    //打印上半部分
    
    int i = 0;
    for (i = 0; i < line; i++)
    {
        //打印空格
        int j = 0;
        for (j = 0; j < line - 1 - i; j++)
        {
            printf(" ");
        }
        //打印*
        for (j = 0; j <2*i+1; j++)
        {
            printf("*");
        }
        printf("\n");
    }
    //打印下半部分
    for (i = 0; i < line - 1; i++)
    {
        int j = 0;
        //打印空格
        for (j = 0; j <=i; j++)
        {
            printf(" ");
        }
        //打印*
        for (j = 0; j<2*(line-1-i)-1; j++)
        {
            printf("*");
        }
        printf("\n");
    }

	return 0;
}

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流继承

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值