目录
练习题一
练习题二
练习题三
练习题四
练习题五
练习题六
练习题七
练习题八
字符串函数
1、strlen
2、strcpy
3、strcat
说明:指针一直以来是C语言中比较难懂的一部分,首先要理解指针的定义、作用,明白*操作符的作用是访问、解引用、指向等。做有关指针运算的题时一定要画图解决,画图能够更清晰地明白指针指向内存的方式,便于我们理解。
练习题一
int main()
{
int a[8] = { 1, 2, 3, 4, 5,6,7,8 };
int* ptr = (int*)(&a + 1);
printf("%d,%d", *(a + 1), *(ptr - 1));
return 0;
}
解析:
&a取出整个数组的地址,类型是数组指针类型,即int(*)[8],+1后跳过整个数组,又强制类型转换为整型指针,此时-1向前移动一个整型,再解引用即得到整数8;a代表数组首元素地址,+1跳过一个整型变量,解引用即得到2
练习题二
//假设p 的值为0x100000
//已知,结构体Test类型的变量大小是20个字节
struct Test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
int main()
{
printf("%pn", p + 0x1);
printf("%pn", (unsigned long)p + 0x1);
printf("%pn", (unsigned int*)p + 0x1);
return 0;
}
解析:
结构体test创建了一个指针变量p,先将20转换为16进制即10100,再转换为16进制即14,所以结果便为0x100014;0x100000转换为无符号长整型后即为1048576,此时它就是一个整数,整数+1就是+1,不会像指针那样还要关注指针类型是几个字节,于是得到1048577,再转换为16进制得100001;一个整型指针是4个字节,0x100000加4就等于0x100004
练习题三
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]->*(ptr1+(-1))->*(ptr1-1) ,ptr[-1]与练习题一相类似,就不作过多说明;a代表首元素地址,强制类型转换为整型后再加1指向01后面,因为又已经被转换为整型指针了,所以解引用后为02000000
练习题四
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int* p;
p = a[0];
printf("%d", p[0]);
return 0;
}
解析:
a[0]表示第一行的数组名,数组名又表示首元素的地址,即a[0][0]的地址,注意此处有逗号表达式,所以a[3][2]={1,3,5},p[0]->*(p+0)->*p,答案为1
练习题五
int main()
{
int a[5][5];
int(*p)[4];
p = a;
printf("%p,%dn", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
return 0;
}
解析:
p[4][2]->*(*(p+4)+2),p[4][2]和a[4][2]的位置如图所示,相减得-4,得到-4的补码再转换为16进制即为FF FF FF FC;打印整型即为-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", *(ptr1 - 1), *(ptr2 - 1));
return 0;
}
解析:
练习题七
#include
int main()
{
char *a[] = {"work","at","alibaba"};
char**pa = a;
pa++;
printf("%sn", *pa);
return 0;
}
解析:
练习题八
int main()
{
char *c[] = {"ENTER","NEW","POINT","FIRST"};
char**cp[] = {c+3,c+2,c+1,c};
char***cpp = cp;
printf("%sn", **++cpp);
printf("%sn", *--*++cpp+3);
printf("%sn", *cpp[-2]+3);
printf("%sn", cpp[-1][-1]+1);
return 0;
}
解析:
字符串函数
1、strlen
注意:strlen函数返回的是在字符串中' '前面出现的字符个数
参数指向的字符串必须要以' '结束
注意函数的返回值是size_t,即无符号整型
学会strlen函数的模拟实现
int main()
{
const char*str1 = "abcdef";
const char*str2 = "bbb";
if(strlen(str2)-strlen(str1)>0)
{
printf("str2>str1n");
}
else
{
printf("srt1>str2n");
}
return 0;
}
这道题的结果是str2>str1,因为strlen返回的是无符号整型,无论如何都大于0
模拟实现strlen:
计数器方式:
size_t my_strlen(const char* str)
{
size_t count = 0;
while (*str != ' ')
{
count++;
str++;
}
return count;
}
int main()
{
char arr[] = "hello world";
size_t a = my_strlen(arr);
printf("%un", a);
return 0;
}
递归的方式:
size_t my_strlen(const char* str)
{
if (*str == ' ')
return 0;
else
return 1 + my_strlen(str+1);
}
int main()
{
char arr[] = "hello world";
size_t a = my_strlen(arr);
printf("%un", a);
return 0;
}
指针-指针的方式
size_t my_strlen(const char* str)
{
char* p = str;
while (*p != ' ')
{
p++;
}
return p-str ;
}
int main()
{
char arr[] = "hello world";
size_t a = my_strlen(arr);
printf("%un", a);
return 0;
}
2、strcpy
注意:源字符串必须以' '结束
会将源字符串中的' '拷贝到目标空间
目标空间必须足够大,以确保能存放源字符串
目标空间必须可变
学会模拟实现
模拟实现strcpy:
char* my_strcpy(char* destination, const char* source)
{
char* ret = destination;
while (*source!=' ')
{
*destination++ = *source++;
}
*destination = *source;
return ret;
}
int main()
{
char arr1[] = "hello ";
char arr2[] = "world";
my_strcpy(arr1, arr2);
printf("%sn", arr1);
return 0;
}
3、strcat
注意:源字符必须以' '结束
目标空间必须足够的大,能容纳下源字符串的内容
目标空间必须可修改
字符串自己给自己追加——死循环
模拟实现strcat:
#include
char* my_strcat(char* destination, const char* source)
{
char* ret = destination;
assert(destination && source);
while (*destination != ' ')
{
*destination++;
}
while (*destination++ = *source++)
{
;
}
return ret;
}
int main()
{
char arr1[] = "hello ";
char arr2[] = "world";
my_strcat(arr1, arr2);
printf("%sn", arr1);
return 0;
}
分享到此结束



