C语言-sizeof()和strlen()求各种数组和指针的结果

发布于:2022-11-09 ⋅ 阅读:(9) ⋅ 点赞:(0) ⋅ 评论:(0)

目录

一、前言

二、基础(前提)知识

三、题目

(一)一维数组

1、整形数组

2、字符数组(情形1)

 3、字符数组(情形2)

4、字符数组(情形3)

(二)二维数组


一、前言

sizeof和strlen的区别:
1、strlen计算字符串的具体长度 (只能是字符串),不包括字符串结束符。返回的是字符个数。

2、strlen的参数是指针类型,所以传过来的参数为指针才对。

size_t strlen ( const char * str );

3、sizeof计算声明后所占的内存数(字节大小),不是实际长度
4、sizeof是一个取字节运算符, 而strlen是个函数。
5、sizeof的返回值=字符个数*字符所占的字节数,字符实际长度小于定义的长度,此时字符个数就等于定义的长度。若未给出定义的大小,分类讨论,对于字符串数组,字符大小等于实际的字符个数+1;对于整型数组,字符个数为实际的字符个数。字符串每个字符占1个字节,整型数据每个字符占的字节数需根据系统的位数类确定,32位占4个字节,48位占8个字节。

二、基础(前提)知识

数组名的意义:

1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
3. 除此之外所有的数组名都表示首元素的地址。 (二维数组的首元素地址指的是第一行元素地址)

三、题目

(一)一维数组

1、整形数组

整形数组只能求sizeof,strlen只能求字符串的具体长度

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

下面来一行行解释:

	printf("%d\n", sizeof(a));

这里是sizeof(数组名)的情况,所以这里的数组名表示整个数组,计算的是整个数组的大小,结果是sizeof(int)*4 = 16。

	printf("%d\n", sizeof(a + 0));

这里的数组名不是直接放在sizeof里,而是+0,就是我们说的第三种情况,也就是代表首元素址,地址分为32位和64位,所以这里的答案是4或者8。

	printf("%d\n", sizeof(*a));

此处a表示首元素地址,进行解引用以后就代表了第一个元素也就是1,所以结果是4。

    

	printf("%d\n", sizeof(a + 1));

同第二条,+1代表指向第二个元素地址,也就是2的地址,结果是4或8。

	printf("%d\n", sizeof(a[1]));

a[1]代表第二个元素2,所以结果为4。

	printf("%d\n", sizeof(&a));

&a就是取出a整个数组的地址,但是它还是一个地址,结果为4或8。

	printf("%d\n", sizeof(*&a));

&a取出了整个数组的地址,解引用以后代表的是整个数组,相当于  int (* p ) [4]=  &a;   一个数组指针, *p代表整个数组

所以结果是16。

	printf("%d\n", sizeof(&a + 1));

&a代表取出整个数组地址,再+1代表直接跨过这个数组到达2的地址位置。结果为4或8。

	printf("%d\n", sizeof(&a[0]));

表示取a[0]的地址,结果是4或8。 

 

	printf("%d\n", sizeof(&a[0] + 1));

取出a[0]的地址再向后跨过一个整形到达第二个元素的地址,结果是4或8。

结果:(32位地址为4个字节,64位地址为8个字节)

 

2、字符数组(情形1)

sizeof()

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

首先明确这里的arr数组里最后是没有\0的。

下面来一行行分析:

	printf("%d\n", sizeof(arr));

arr直接放到sizeof里面,数组名表示整个数组,计算的是整个数组的大小,结果为6。

	printf("%d\n", sizeof(arr + 0));

arr不是直接放到sizeof里,而是+0,所以这里的数组名就代表了首元素地址,+0表示没有向后移动,所以结果是4或8。

	printf("%d\n", sizeof(*arr));

arr是首元素地址,*arr就是把首元素地址解引用,就是‘a’这个元素,所以结果为1。

	printf("%d\n", sizeof(arr[1]));

arr[1]代表数组的第二个元素,是'b',所以结果为1。

	printf("%d\n", sizeof(&arr));

&arr取出的是整个数组的地址,但它还是一个地址,所以结果为4或8。

	printf("%d\n", sizeof(&arr + 1));

&arr取出的是整个数组的地址,+1表示跨过了这个数组到达下一块地址位置,结果为4或8。

	printf("%d\n", sizeof(&arr[0] + 1));

&arr[0]代表取出数组第一个元素地址,+1表示向后挪动一个字节到达第二个元素地址,也就是‘b’的地址,结果为4或8。

结果:(32位地址为4个字节,64位地址为8个字节))

strlen()

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));
	return 0;
}

 下面来一条条解释:

	printf("%d\n", strlen(arr));

这里arr表示的是首元素地址,但是因为此数组最后没有‘\0’字符串结束符,所以strlen数的时候停不下来,所以结果为随机值。

	printf("%d\n", strlen(arr + 0));

同上,arr+0代表的还是数组首元素地址,结果为随机值。

	printf("%d\n", strlen(*arr));

*arr表示解引用首元素地址,就是‘a’,但是strlen()这个函数的参数接收的是地址,所以此条语句错误。

	printf("%d\n", strlen(arr[1]));

同上,这里的a[1]指的是元素‘b’,此条语句错误。

	printf("%d\n", strlen(&arr));

&a代表取出a整个数组的地址,但是这个地址是指向首元素的地址的,于是传给strlen就是数组首元素地址,但是数组没有字符结束符,所以结果为随机值。

	printf("%d\n", strlen(&arr + 1));

这条的意思前面已经解释过两遍,就是指向arr数组后的地址空间,所以是随机值,但是这个随机值会比上一条的随机值少6,因为arr数组里有六个元素,所以也可以写成 随机值 - 6。

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

取出的是arr数组的第二个元素‘b’,但因为没有字符结束符,结果还是随机值,但这个随机值比上上条随机值少1,所以也可以写成随机值 - 1。

结果:(32位)(把两个错误语句屏蔽以后)

 3、字符数组(情形2)

sizeof()

#include <stdio.h>

int main() {
	char arr[] = { "abcdef" };
	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;
}

首先明确这里的arr数组里最后是有\0的。sizeof()会算上最后的‘\0’。

所以这段代码除了第一条

	printf("%d\n", sizeof(arr));

的结果会多一个'\0',也就是6 + 1 = 7,以外,其他分析和结果不变。

结果:(32位)

strlen()

#include <stdio.h>

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

下面来一条条分析:

	printf("%d\n", strlen(arr));

arr表示数组首元素地址,而数组后面有字符串结束符‘\0’,而strlen计算本身并不包括'\0',所以结果为6。

	printf("%d\n", strlen(arr + 0));

arr+0还是表示首元素地址,结果为6。

	printf("%d\n", strlen(*arr));

 *arr表示首元素,但是strlen得接受地址,所以此条代码错误。

	printf("%d\n", strlen(arr[1]));

arr[1]代表数组第二个元素,理由如上条,此条代码错误。

	printf("%d\n", strlen(&arr));

&arr表示取出整个数组地址,但是传过去的值是首元素地址,所以结果为6。

	printf("%d\n", strlen(&arr + 1));

&arr + 1表示越过arr数组到 arr后面的地址空间,所以是随机值。

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

&arr[0],表示区第一个元素的地址,+1代表往后走一个字节(因为是char类型),取到了第二个元素的地址,所以结果为5。

结果:(32位)(把两条错误代码屏蔽以后)

4、字符数组(情形3)

sizeof()

#include <stdio.h>

int main() {
	char* p = "abcedf";
	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;
}

相当于将上面的arr数组的首元素地址放进指针p里。

下面来一条条分析:

	printf("%d\n", sizeof(p));

p是指针,结果是4或8。

	printf("%d\n", sizeof(p+1));

p+1还是一个地址,结果为4或8。

	printf("%d\n", sizeof(*p));

p是指向数组首元素的指针,*p指的就是‘a’,结果为1。

	printf("%d\n", sizeof(p[0]));

p[0]相当于情形2中的arr[0],相当于*(p  +  0),指的还是‘a’,结果为1。

	printf("%d\n", sizeof(&p));

p本身为指针,&p也还是一个地址,结果为4或8。

	printf("%d\n", sizeof(&p + 1));

&p为地址,+1取出的是p后面那块内存空间的地址,结果为4或8。

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

&p[0]取出的是首元素的地址,+1代表第二个元素的地址,结果为4或8。

结果:(32位)

strlen()

#include <stdio.h>

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

 下面来一条条分析:

	printf("%d", strlen(p));

p是一个指向'a'地址的指针,strlen(p)就相当于把'a'的地址作为参数,结果为6。

	printf("%d", strlen(p + 1));

p + 1就是跳过一个char型指向'b'的地址,结果是5。

	printf("%d", strlen(*p));

p是指向'a'地址的指针,*p获取的就是'a',但是strlen的参数是指针,所以此条语句错误。

	printf("%d", strlen(p[0]));

p[0] 相当于*(p + 0),取出来的就是'a',词条语句错误。

	printf("%d", strlen(&p));

已知p是指向'a'地址的指针,此数组里有\0可以让strlen停下来。&p取出来的是p这个指针的地址,可是p里面存放了什么我们并不知道,所以是随机值。

	printf("%d", strlen(&p + 1));

&p + 1指的是取到了p后面的地址空间,结果为随机值。

 

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

&p[0]渠道的是'a'这个元素的地址,+1就跳过一个char型,取到'b'的地址,结果是5。

结果:(32位)

 

 

(二)二维数组

#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]));
}

画个图帮助大家理解:

 下面来一条条解释:

	printf("%d\n", sizeof(a));

a单独放在sizeof()里面表示的是整个数组,结果为3 * 4 * 4(int) = 48。

	printf("%d\n", sizeof(a[0][0]));

a[0][0]表示a的第一行第一个元素,结果是4。

	printf("%d\n", sizeof(a[0]));

a[0]代表第一行的数组名,数组名单独放在sizeof()里表示整个数组,于是这里的结果就是第一行的元素个数 * sizeof(int)= 16。

 

printf("%d\n", sizeof(a[0] + 1));

此时a[0]既单独放在 sizeof()内部,也没有&,所以这里的a[0]表示首元素地址也就是a[0][0]地址,+1则跳过一个int型,表示a[0][1]的地址,结果为4或8。

	printf("%d\n", sizeof(*(a[0] + 1)));

a[0] + 1表示第一行第二个元素的地址,解引用表示这个元素,结果为4。

	printf("%d\n", sizeof(a + 1));

a表示首元素地址,二位数组的首元素表示第一行的地址,+1跳过一行来到a[1],表示第二行的地址,所以结果为4或8。

	printf("%d\n", sizeof(*(a + 1)));

a+1表示第二行的地址,解引用表示第二行,所以计算的是第二行的大小,结果为16。

	printf("%d\n", sizeof(&a[0] + 1));

&a[0]表示取出第一行的地址,+1表示第二行的地址,结果为4或8。

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

&a[0] + 1取出的是第二行的地址,解引用表示第二行,计算的是第二行的大小,结果为16。

	printf("%d\n", sizeof(*a));

a表示首元素地址即第一行的地址,*a表示第一行大小,结果为16。

*a <----> *(a+0) <----> a[0]

	printf("%d\n", sizeof(a[3]));

a[3]单独放在sizeof()里理论上来说是数组第四行,虽然数组没有第四行,但是由于sizeof()内部的表达式并不会被真正访问,是不参与运算的,所以结果为16。

结果:(32位)

 

结束啦~~散花~~

有什么作者写的不对的地方欢迎在评论区指正哦,请多多的点赞吧!谢谢大家qaq