德阳住房和城乡建设厅网站,wordpress 禁用修订,咸阳学校网站建设费用,一个企业可以做多个网站吗本文分为两部分 #xff0c;第一部分为数组、字符串、字符指针在sizeof和strlen中的辨析#xff0c;第二部分是一些笔试题目。若有错误#xff0c;请批评指正。 目录
1.第一部分
1.1.数组名的使用
1.1.1一维整型数组在sizeof中的使用
1.1.2一维字符数组在sizeof中的使用… 本文分为两部分 第一部分为数组、字符串、字符指针在sizeof和strlen中的辨析第二部分是一些笔试题目。若有错误请批评指正。 目录
1.第一部分
1.1.数组名的使用
1.1.1一维整型数组在sizeof中的使用
1.1.2一维字符数组在sizeof中的使用
1.1.3一维字符数组在strlen中的使用
1.1.4.一字符串在sizeof中的使用
1.1.5.一字符串在strlen中的使用
1.2字符指针在sizeo和strlen中的使用
1.2.1 字符指针在sizeof中的使用
1.2.2 字符指针在strlen中的使用
2.第二部分指针笔试题 1.第一部分
注意 1.sizeof()是操作符只关注占用的内存空间的大小单位是字节不访问内存中的存储的内容。 2.strlen()是库函数用来求字符串的长度统计的是字符\0出现之前的字符的个数当函数在内存中找到’\0‘才算结束所以strlen可能会越界访问。 3.以下所有的代码均在32位的环境中因此地址为4个字节。 3.数组名字的意义 1. sizeof(数组名)这里的数组名表示整个数组计算的是整个数组的大小。 2. 数组名这里的数组名表示整个数组取出的是整个数组的地址。 3. 除此之外所有的数组名都表示首元素的地址。 1.1.数组名的使用
1.1.1一维整型数组在sizeof中的使用
int main()
{int a[] { 1,2,3,4 };printf(%d\n, sizeof(a)); //16 ()中只有数组名表示整个数组所测量的是整个数组printf(%d\n, sizeof(a 0));//a0就是数组首元素的地址地址的大小为4个字节printf(%d\n, sizeof(*a));//*a表是的数组首元素是一个整型变量 4个字节//a不是单独存在时表示的首元素地址*a就是元素 1 printf(%d\n, sizeof(a 1));//a为首元素地址1之后还是地址 4个字节printf(%d\n, sizeof(a[1]));// 数组第二个元素 4个字节printf(%d\n, sizeof(a));//a数组指针地址为 4个字节printf(%d\n, sizeof(*a));// * 两者相互抵消是整个数组 16个字节printf(%d\n, sizeof(a 1));//是地址指向的是第二个元素 4个字节printf(%d\n, sizeof(a[0])); //首元素地址 4个字节printf(%d\n, sizeof(a[0] 1)); //第二个元素地址 4个字节return 0;
}
1.1.2一维字符数组在sizeof中的使用
int main()
{char arr[] { a,b,c,d,e,f };//char类型数据大小为一个字节printf(%d\n, sizeof(arr));// 6个字节arr单独存放是整个数组printf(%d\n, sizeof(arr 0));//4个字节arr0表示为首元素地址printf(%d\n, sizeof(*arr));// 1个字节 arr表示首元素地址*arr为首元素aprintf(%d\n, sizeof(arr[1]));// 1个字节第二个元素bprintf(%d\n, sizeof(arr));//4个字节 数组指针arr为地址printf(%d\n, sizeof(arr 1));//4个字节 地址加1还是地址数据类型不变printf(%d\n, sizeof(arr[0] 1));//4个字节 取首元素的地址1还是地址return 0;
}
1.1.3一维字符数组在strlen中的使用 strlen 的返回值是字符的个数形式参数是字符指针
size_t strlen ( const char * str ); size_t 无符号整型返回值 const char * str 字符指针形式参数 const为关键字限定str无法修改 int main()
{char arr[] { a,b,c,d,e,f };printf(%d\n, strlen(arr)); //随机值,arr为数组的首元素地址但是数组中没有\0printf(%d\n, strlen(arr 0));//arr0arr是地址0之后还是地址函数无法接受printf(%d\n, strlen(*arr)); //表示是a— 97,非法访问printf(%d\n, strlen(arr[1])); //表示是b— 98非法访问printf(%d\n, strlen(arr)); //数组指针是指针会报警的但是从数组指针开始计算还是随机值printf(%d\n, strlen(arr 1));// 数组指针1 之后地址跳过数组随机值printf(%d\n, strlen(arr[0] 1));//表示的是第二个元素的地址也是随机值return 0;
}
1.1.4.一字符串在sizeof中的使用
int main()
{char arr[] abcdef;//数组中的元素是 a b c d e f \0 共7个元素printf(%d\n, sizeof(arr)); // 7个字节,数组名字单独存放就是整个数组printf(%d\n, sizeof(arr 0));//4个字节 arr0表示arr[0],首元素地址printf(%d\n, sizeof(*arr)); // 一个字节printf(%d\n, sizeof(arr[1])); // 一个字节printf(%d\n, sizeof(arr)); // 四个字节printf(%d\n, sizeof(arr 1));// 四个字节printf(%d\n, sizeof(arr[0] 1));// 四个字节return 0;
}
1.1.5.一字符串在strlen中的使用 数组名在strlen函数中仍然是首个元素的地址。
int main()
{char arr[] abcdef;//数组中的元素是 a b c d e f \0 共7个元素printf(%d\n, strlen(arr)); // 6 字符串中有6个字符 \0 不算在内printf(%d\n, strlen(arr 0));//6 表示arr[0]首元素的地址printf(%d\n, strlen(*arr));//*arr是a非法访问 printf(%d\n, strlen(arr[1]));//arr[1]是b,属于非法访问printf(%d\n, strlen(arr));//6 arr是数组指针printf(%d\n, strlen(arr 1));// 5 arr是数组指针但是其指向的仍然是数组的首元素处// 1 之后指向数组的第二个元素跳过了第一个元素 printf(%d\n, strlen(arr[0] 1));// 5 一个元素的地址 1 跳过了 第一个元素return 0;
}
1.1.6二维数组在sizeof中的使用 二维数组的数组名表示的是首行元素的地址是数组指针。arr[0]是第一行数组。
int main()
{int a[3][4] { 0 };printf(%d\n, sizeof(a));// 48个字节一共12个元素一个元素 4个字节printf(%d\n, sizeof(a[0][0]));// 第一个元素 4 个字节printf(%d\n, sizeof(a[0]));// 第一行数组 a[0]是第一行数组的名字单独存在即一个数组 16个字节printf(%d\n, sizeof(a[0] 1));//a[0]为首元素地址,1跳到第二个元素地址4个字节printf(%d\n, sizeof(*(a[0] 1)));// 4个字节 第二个元素printf(%d\n, sizeof(a 1));// a 1表示是a[1]是第二行地址 4个字节printf(%d\n, sizeof(*(a 1)));// 表示的是第二行的数组 16个字节printf(%d\n, sizeof(a[0] 1));// a[0]是第一行的地址1 指是第二行的地址 4个字节printf(%d\n, sizeof(*(a[0] 1)));//第二行有四个元素 16个字节printf(%d\n, sizeof(*a));//a为首元素地址就是第一行的地址 16个字节printf(%d\n, sizeof(a[3]));//访问的是数组的第四行元素数组越界但是可以计算//sizeof()中表达式是不会计算的不会访问真是的空间按照类型出的结果。// *a -- *(a0) -- a[0]return 0;
}
1.2字符指针在sizeo和strlen中的使用
1.2.1 字符指针在sizeof中的使用
int main()
{char *p abcdef;printf(%d\n, sizeof(p));//p为指针 4个字节printf(%d\n, sizeof(p 1));// 1 跳出整个字符串地址4个字节printf(%d\n, sizeof(*p));// p 指向的第一个元素 *p 就为 a 1个字节printf(%d\n, sizeof(p[0]));// p[0] --*(p0),首个元素 1个字节printf(%d\n, sizeof(p));// 二级指针 4个字节 printf(%d\n, sizeof(p 1));// 二级指针 1 还是指针 4个字节printf(%d\n, sizeof(p[0] 1));//第一个元素的指针 1 表示的第二个元素的指针 4个字节 return 0;
}
1.2.2 字符指针在strlen中的使用
int main()
{char *p abcdef;printf(%d\n, strlen(p));// p是一个指向a的一个字符指针 6printf(%d\n, strlen(p 1));// 5 指针1 指针指向的是 bprintf(%d\n, strlen(*p));// 非法访问printf(%d\n, strlen(p[0]));// 相当于 *p0非法访问printf(%d\n, strlen(p));// 二级指针 随机值printf(%d\n, strlen(p 1));// 随机值 printf(%d\n, strlen(p[0] 1)); //5 p[0]相当于p了 p1指向第二个元素return 0;
}
2.第二部分指针笔试题
本部分共八个题目
1.
int main()
{int a[5] { 1, 2, 3, 4, 5 };int *ptr (int *)(a 1); // a1 已经跳出整个数组了 //强制转换成int*类型的指针 printf(%d,%d, *(a 1), *(ptr - 1));//a1中的a为首元素地址 a1 只想第二个元素return 0;
}
//结果为 25
分解
1第4行
int *ptr (int *)(a 1); a为数组指针指向的是数组的首元素地址所以a1就可以跳出整个数组1它的步长就是整个数组的长度。 int*为强制转换类型(int *)(a 1)可以把数组指针a1强制转换成整型指针并且将指针的值赋予ptr那么ptr的值和a1是一样的但是其类型步长是不一样的
printf(%d,%d, *(a 1), *(ptr - 1)) a1中的a表示首元素的地址a1表示是第二个元素的地址*a1解引用的就是 2
*ptr-1ptr的地址向低地址移动四个字节指向的是第五个元素。*ptr-1为5。
2.
#include stdio.h
struct Test
{int Num;char *pcName;short sDate;char cha[2];short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少
//结构体的大小是20字节
int main()
{int p 0x100000;printf(%p\n, p 0x1);//p1 0x1000000x10x100001printf(%p\n, (unsigned long)p 0x1);//强制转换成 无符号整型 0x100001printf(%p\n, (unsigned int*)p 0x1);//强制转换成无符号整型指针 1 就是0x4 结果为 0x100004 return 0;
} 上述程序结果为0x00100001 0x00100001 0x00100004 *p为结构体指针但是此题中根本没有使用到结构体指针的大小和指向等问题
printf(%p\n, p 0x1); 0x1对于十进制来说就是1但是输出的是%p形式以地址的方式输出要输出8位数字。
p0x1000000x10x100001输出的是0x00100001。
printf(%p\n, (unsigned long)p 0x1); (unsigned long)p 将p强制转换成无符号整型但是输出的仍然是地址的形式因此和上面1计算一样结果都是 0x00100001。
printf(%p\n, (unsigned int*)p 0x1); (unsigned int*)p 将p强制转换成无符号指针类型其大小为4个字节1步长为4个字节
因此p1就是指针加4结果就是0x001000010x4输出为0x00100001。
3.
//机器为小端存储
int main()
{int a[4] { 1, 2, 3, 4 };int *ptr1 (int *)(a 1);int *ptr2 (int *)((int)a 1);//a为数组的第一个元素的指针强制转换成int 图解//数组a 的存储方式 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00printf(%x,%x, ptr1[-1], *ptr2);//ptr[-1]-- *(ptr-1)return 0;
}
//结果 0x4 0x2000000//%x就是打印16进制的字符 数组元素的存储方式为小端存储小端存储就是数据低位放在地址值数据高位放在高地址。
a[4]数组在内存中的存储方式每一个小方块为一个字节有8个bit的内存。 int *ptr1 (int *)(a 1); a为数组指针指向的是数组的首元素地址所以a1就可以跳出整个数组1它的步长就是整个数组的长度。
int *ptr2 (int *)((int)a 1) a为数组名是首元素地址强制转化成int类型1就是数字1强制转换成int*类型a在原来地址的基础上向高地址挪动一个字节相当于指向第一个整型元素的第2个字节。*ptr输出的是整型元素需要从低地址到高地址四个字节从第一个元素的第二个字节到第二个元素的第一个字节因此 *ptr就是 0x2000000 。
4.
#include stdio.h
int main()
{int a[3][2] { (0, 1), (2, 3), (4, 5) };//int a[3][2] {1,3,5};int *p;p a[0];//a[0]是第一行的数组名是第一行的首元素地址printf(%d, p[0]);//p[0] -- *(p0)return 0;
} 结果为 1 。
int a[3][2] { (0, 1), (2, 3), (4, 5) } 01逗号表达式表达式从左向右最后表达式的结果就是整个表达式的结果。那么得出
int a[3][2] { 1, 3, 5 }
p a[0] a[0]为二维数组首行数组的名字数组名字就是首元素的地址将首元素地址赋值给p输出的自然是首元素1啊。
5.
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 -4
}a等价于 int (*)[5] 指向是元素为5的数组
p等价于 int (*)[4] 指向是元素为4的数组
根据图p[4][2] - a[4][2]相差四个元素 结果为-4
-4 的原码 10000000 00000000 00000000 00000100反码 10000000 00000000 00000000 00000011补码 11111111 11111111 11111111 111111100 地址不会区分原码、反码 、补码地址就是内存中存储的补码。转换成16进制 ff ff ff fc
p a; 将a的int (*[5]的数值强行赋值给了pp的类型是int (*[4]指向的是四个指针的数组。
a为首元素地址是第一行的数组指针类型是int (*[5]。
数组在内存中存储的排序为 强制复制后p就为a地址但是p指向的是int[4]类型的数组因此步长为4个整型数据假设所模拟后的数组为4个元素为一行。 图解 p[4][2] - a[4][2], 可以看出其中间相差4个步长数值为-4。
6.
7.
8.