一.sizeof和strlen的对比
1.sizeof
sizeof是操作符,不是函数!!!
计算的是类型,变量和表达式所占用内存的大小,单位是字节不关注内存里放的是什么内容,且当sizeof里放的是表达式的时候,表达式不计算。
int main(){
int a=10;
printf("%zd\n",sizeof(a));
printf("%zd\n",sizeof(int));//计算类型大小时,必须加(),变量和表达式可以不加。
printf("%zd\n",sizeof a);//验证了sizeof不是函数。
return 0;
}
2.strlen
而strlen是库函数,计算的是字符串的长度。他的头文件是<string.h>,参数是一个指针变量,统计的是从这个指针所指的位置到\0为主的字符个数,会关注内存中有没有\0,没有就会向后访问,可能会越界。
size_t strlen(const char* p);//函数原型
#include <string.h>
int main() {
char arr1[3] = { 'a','b','c' };
char arr2[] = "abc";
printf("%zd\n", sizeof(arr1));//3
printf("%zd\n", sizeof(arr2));//4
printf("%zd\n", strlen(arr1));//不确定
printf("%zd\n", strlen(arr2));//3
return 0;
}
二.数组和指针相关题目
1.一位数组
int main(){
int a[] = { 1,2,3,4 };
printf("%zd\n", sizeof(a));//a是数组名,sizeof计算的是整个数组的大小,单位是字节,-16
printf("%zd\n", sizeof(a + 0));//a没有单独放在sizeof()里面,是数组首元素的地址,加0还是地址,大小是4/8.
printf("%zd\n", sizeof(*a));//*a是数组首元素 -4
printf("%zd\n", sizeof(a + 1));//a+1是数组第二个元素的地址 -4/8
printf("%zd\n", sizeof(a[1]));//第二个元素 -4
printf("%zd\n", sizeof(&a));//&a取出整个数组的地址 -4/8
printf("%zd\n", sizeof(*&a));//*和&相互抵消,计算的是整个数组的大小 -16
printf("%zd\n", sizeof(&a + 1));//整个数组的地址加1还是地址 -4/8
printf("%zd\n", sizeof(&a[0])); //第一个元素的地址 -4/8
printf("%zd\n", sizeof(&a[0] + 1));//第二个元素的地址 -4/8
return 0;
}
2.字符数组
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr));//arr是数组名,计算的是整个数组的大小,-6
printf("%d\n", sizeof(arr + 0));//arr没有单独放在sizeof里,是数组首元素的地址-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;
}
#include <string.h>
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", strlen(arr));//数组中没有\0,不确定在后面的内存什么时候出现
printf("%d\n", strlen(arr + 0));//首元素的地址开始找\0
printf("%d\n", strlen(*arr));//参数是'a',ascll值是97,传递的可能是野指针
//这是错误的代码,传给他的应该是个指针变量
printf("%d\n", strlen(arr[1]));//传递的'b',98,同理,error
printf("%d\n", strlen(&arr));//从整个数组的地址开始也不确定\0的位置 x
printf("%d\n", strlen(&arr + 1));//同理,从数组后的指针开始也不确定 x-6
printf("%d\n", strlen(&arr[0] + 1));//第二个元素的地址开始 x-1
return 0;
}
int main()
{
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));//整个数组长度 7
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;
}
#include <string.h>
int main()
{
char arr[] = "abcdef";
printf("%d\n", strlen(arr));//整个数组的长度 6
printf("%d\n", strlen(arr + 0));//首元素的地址 6
printf("%d\n", strlen(*arr));//首元素 97 error
printf("%d\n", strlen(arr[1]));//第二个元素 98 error,野指针
printf("%d\n", strlen(&arr));//整个数组的地址 6
printf("%d\n", strlen(&arr + 1));//数组之后的地址开始 不确定
printf("%d\n", strlen(&arr[0] + 1));//第二个元素的地址 5
return 0;
}
int main()
{
const char * p = "abcdef";
printf("%d\n", sizeof(p));//p是'a'的地址,4/8
printf("%d\n", sizeof(p + 1));//'b'的地址 4/8
printf("%d\n", sizeof(*p));//'a' 1
printf("%d\n", sizeof(p[0]));//1
printf("%d\n", sizeof(&p));//二级指针,指向的是p 4/8
printf("%d\n", sizeof(&p + 1));//4/8
printf("%d\n", sizeof(&p[0] + 1));//第二个元素地址 4/8
return 0;
}
int main()
{
char* p = "abcdef";
printf("%d\n", strlen(p));//6
printf("%d\n", strlen(p + 1));//5
printf("%d\n", strlen(*p));//error
printf("%d\n", strlen(p[0]));//error
printf("%d\n", strlen(&p));//从二级指针开始计数,不确定到\0的个数,二级指针指向的空间与p指向的无关
printf("%d\n", strlen(&p + 1));//不确定
printf("%d\n", strlen(&p[0] + 1));//'b'的地址 5
return 0;
}
3.二维数组
int main()
{
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));//整个数组的大小 48
printf("%d\n", sizeof(a[0][0]));//4
printf("%d\n", sizeof(a[0]));//a[0]是第一行数组的名字,计算的是第一行数组的大小 16
printf("%d\n", sizeof(a[0] + 1));//第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]));//第4行的大小 16
return 0;
}
三、指针运算题
#include <stdio.h>
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int* ptr = (int*)(&a + 1);//取出整个数组的地址然后加1还是数组指针,指向a数组后面的位置,强制类型转换成整型指针赋给ptr,减1解引用后就是5
printf("%d,%d", *(a + 1), *(ptr - 1));//2,5
return 0;//首元素地址加一指向第二个元素,解引用是2.
}
在X86(32位)环境下
假设结构体的大小是20个字节
程序输出的结果是啥?
struct Test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
} * p = (struct Test*)0x100000;
//结构体指针变量p,用一个被强制类型转换的数值初始化
int main()
{
printf("%p\n", p + 0x1);//0x1就是1,指针加1看他的类型,那么就跳过一个结构体类型,20个字节,一个字节有一个地址,那就是0x100020吗?不是的,应该先转化成16进制的,是0x100014.用指针打印就是00100014
printf("%p\n", (unsigned long)p + 0x1);//将p强转为一个数字,加1就是真的加1,答案是0x100001,打印出来就是00100001
printf("%p\n", (unsigned int*)p + 0x1);
//将p强转为整型指针,加1就跳过4个字节,打印为地址就是00100004.
return 0;
}
#include <stdio.h>
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };//初始化应该也用{},但现在里面相当于括号表达式,从最左边的表达式依次开始计算,结果是最后一个表达式的结果。这里是
{1,3,
5,0,
0,0};
int* p;
p = a[0];//p是第一行的地址
printf("%d", p[0]);这里是第一行第一个元素 1
return 0;
}
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]);
//随下标增大,地址也逐渐增大,用%d打印是-4,在内存中以二进制补码表示 原码 10000000000000000000000000000100
//反码 11111111111111111111111111111011
//补码 11111111111111111111111111111100
//补码直接被当做以地址打印出来就是16进制的fffffffc
return 0;
}

#include <stdio.h>
int main()
{
int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int* ptr1 = (int*)(&aa + 1);//指向的是10后面的地址,被强转为整型指针,后面操作减1就指向10的空间
int* ptr2 = (int*)(*(aa + 1));//指的是第二行首元素的地址
printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));//10和5
return 0;
}
#include <stdio.h>
int main()
{
char* a[] = { "work","at","alibaba" };
char** pa = a;
pa++;
printf("%s\n", *pa);//at
return 0;
}

#include <stdio.h>
int main()
{
char* c[] = { "ENTER","NEW","POINT","FIRST" };
char** cp[] = { c + 3,c + 2,c + 1,c };
char*** cpp = cp;
printf("%s\n", **++cpp);//POINT
printf("%s\n", *-- * ++cpp + 3);//ER
printf("%s\n", *cpp[-2] + 3);//ST
printf("%s\n", cpp[-1][-1] + 1);//EW
return 0;
}

1896

被折叠的 条评论
为什么被折叠?



