sizeof
1.sizeof是操作符
2.sizeof计算操作数所占内存的大小,单位是字节(byte)
3.sizeof不关注内存中存放什么数据
4.sizeof比较通用不挑类型
strlen
1.strlen是库函数,使用需包含头文件string.h
2.strlen是求字符串长度的,统计的是 \0 之前的字符的个数
3.strlen关注内存中是否有 \0 ,如果没有 \0 ,就会持续向后找,可能会越界
4.strlen只能用于求字符串长度
sizeof
sizeof 是操作符,不是函数
当sizeof后接变量或数组时,()可省,证明了sizeof不是函数,
因为函数在调用时函数调用操作符()不可省
#include <stdio.h>
int main()
{
int a = 10;
printf("%d\n", sizeof(a));
printf("%d\n", sizeof a);
printf("%d\n", sizeof(int));
return 0;
}
当sizeof后接类型名时,()不可省
在这里,介绍一个类型size_t , size_t是专门设计给sizeof的,用于表示sizeof的返回值类型,即无符号整数类型,在打印时也可使用%zd代替%d
下面为一段sizeof应用实例
#include<stdio.h>
int main()
{
short s = 10;
int i = 2;
int n = sizeof(s = i + 4);
printf("%d\n", n);
printf("%d\n", s);
return 0;
}
请问:输出结果为多少
输出结果:
n的值为什么为2呢?
因为sizeof在计算大小的时候是根据类型推算的
short类型大小为两个字节,int类型大小为四个字节
我们无法将四米长的棍子放进两米长的房间,同样的,我们也无法将int类型的数据完整存放在short类型中,此时就要发生截断,所以n的值为2
s的值为什么是10呢?
当sizeof的操作数为表达式时,表达式是不参与计算的
为什么表达式放到sizeof中就不参与计算了呢?
我们知道,表达式有两个属性:
1.类型属性
2.值属性
sizeof根据类型属性推断
源文件(源代码)----------编译--------链接--------可执行程序-----------计算/运算
test.c sizeof test.exe s=i+4
sizeof(s=i+4)在编译时就已确定大小,即在编译时发生了
int n=sizeof(s=i+4);------------>int n=2;
因为在编译时表达式就已被替换,所以后续计算失效,s=i+4 根本不执行,所以sizeof里面的表达式不参与计算
你是否明晰了sizeof的使用呢?做几道题检测一下吧
🌰:一:
#include<stdio.h>
int main()
{
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;
}
想作对这道题,除了了解sizeof的使用,还需知晓数组名的含义
数组名的含义
数组名即为数组首元素地址,但有两个例外
🌰1:sizeof(数组名),数组名表示整个数组,计算的是整个数组的大小,单位是字节
🌰2:&数组名,数组名表示整个数组,取出的是整个数组的地址
知晓了以上内容我们再来分析这道题
1.数组名单独放在sizeof内部,计算整个数组的大小(4*4=16)
2.数组名没有单独放在sizeof内部,此时数组名为首元素地址,a+0还是数组首元素地址,地址大小为4/8字节(取决于编译环境)
3.对数组首元素地址解引用,得到的是数组首元素,数组首元素类型为int,大小为4字节
4.a+1为数组第二个元素的地址即&a[1],地址大小为4/8字节(取决于编译环境)
5.a[1]计算第二个元素大小,由于该元素类型为int,所以结果为4字节
6.&a取出的为整个数组的地址,但数组的地址也是地址,地址大小不会改变(不会因为是数组地址就变大或是char类型的变量就变小),大小就是4/8字节
7.(1).*&相互抵消sizeof(*&a)==sizeof(a),计算的为整个数组的大小
(2).&a先取出整个数组的地址
而*(解引用操作符)到底访问多少由指针类型决定,此时指针的类型为int(*)[4],故访问整个数组
8.*&a访问的是整个数组,&a+1跳过的也为整个数组,此时计算的是a数组后面的那个地址,地址大小为4/8字节
9.数组首元素地址,大小4/8
10.数组第二个元素的地址,大小4/8
🌰二:
#include<stdio.h>
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(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.sizeof数组名,计算整个数组的大小,即为1*6=6字节
2.数组首元素地址,大小为4/8字节
3.*arr得到的为数组首元素,数组首元素类型为char,大小为1字节
4.arr[i]==*(arr+i),arr[1]即为数组第二个元素
5.整个数组的地址也是地址,大小为4/8字节
6.&arr+1跳过整个数组,指针指向的为数组后面那个元素,地址大小为4/8字节
7.&arr[0]+1为数组第二个元素的地址,大小为4/8字节
🌰三:
#include<stdio.h>
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;
}
1.sizeof(数组名)计算的为整个数组的大小,即为48(3*4*4)字节
2.a[0][0]为数组第一个元素,大小为4字节
3.a[0]就是第一行的数组名,单独放在sizeof内部,计算的为第一行的大小,即为4*4=16
4.a[0]是第一行数组名,但数组名并未单独放在sizeof内部,所以数组名表示的是数组首元素地址,也就是a[0][0]的地址,a[0]+1是a[0][1]的地址,地址的大小为4/8字节
5.a[0]+1即&a[0][1],对该指针进行解引用操作,即元素a[0][1],由于是整形二维数组,元素为整形,大小为4字节
6.a没有单独放在sizeof内部,数组名a就是数组首元素的地址,也就是第一行的地址,a+1就是第二行的地址,地址大小为4/8字节
7.对第二行地址解引用访问第二行,大小为4*4=16字节
8.&a[0]取出的是第一行的地址,&a[0]+1得到的就为第二行的地址,地址大小4/8字节
9.对第二行地址解引用访问第二行,大小为4*4=16字节
10.数组名a就是数组首元素的地址,也就是第一行的地址,*a就是访问第一行,大小为4*4=16字节 --> *a ==*(a+0)==a [ 0 ];
11.a[3]和a[0]性质相同,sizeof不会访问内容,大小仍为16字节
strlen
strlen是C语言库函数,功能为求字符串长度,统计的为从strlen函数的参数地址向后,\0 之前字符串中字符的个数,strlen函数会一直向后查找 \0 字符,直到找到为止,所以可能存在越界查找与提前终止。
下面来几段应用实例
代码1:
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = "abcdef";
printf("%d\n", strlen(arr));
return 0;
}
这段代码打印结果为6,向后查找至 \0 停止,\0 不计入总数(sizeof中\0计入总数)
代码2:
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = "abc\0def";
printf("%d\n", strlen(arr));
return 0;
}
这段代码运行结果为3,遇见 \0 提前终止
代码3:
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = { 'a','b','c' };
printf("%s\n", arr);
printf("%d\n", strlen(arr));
return 0;
}
这段代码的输出结果为 abc+随机值 和 随机值,在初始化时未加入终止字符(\0)导致打印字符串其后为随机值,strlen函数向后越界查找遇见 \0 才停止
会了没会了没会了没
再做几道题试试吧!!!
🌰一:
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
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));
}
下面不想写上面不想看,就这样吧看得开心就行。。。
我要爬山去了(西上北下)