0
点赞
收藏
分享

微信扫一扫

java并发-AQS

知年_7740 2023-05-16 阅读 27
#define _CRT_SECURE_NO_WARNINGS 1

#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));//随机数a
	printf("%d\n", strlen(&arr + 1));//随机数a-6
	printf("%d\n", strlen(&arr[0] + 1));//随机数a-1

	return 0;
}

问:C语言中,strlen()必须接收一个地址才行吗?
ChatIA答:
是的,strlen() 函数需要接收一个字符数组的地址,也就是一个指向字符数组首个元素的指针。这是因为 strlen() 函数的作用是计算字符串的长度,而字符串是以 null 字符(‘\0’)结尾的字符数组。因此只有通过传递指向字符数组首个元素的指针,才能让 strlen() 函数在字符数组中扫描查找 null 字符并计算字符串的长度。

如果你传递的不是字符数组的首个元素的指针,那么 strlen() 函数无法确定字符数组的起始位置,而且可能还会读取无效内存,导致程序出现错误。因此强烈建议在调用 strlen() 函数时传递字符数组的地址。

问:上述代码中,当strlen(&arr)时,VS2015环境下报错“const char ”与“char ()[6]”的间接级别不同。
ChatAI答:
是的,“const char*” 和 “char (*)[6]” 的间接级别是不同的。

对于前者,它是一个指向字符的常量指针(或者说是指向字符串的指针),并且是单个字符的指针。指针加1时,指向的是下一个字符,因此它是一个指向内存中某个连续字符单元的指针。

对于后者,它是一个指向字符数组的指针,该字符数组有6个元素。指针加1时,指向的是下一个数组,因此它是一个指向一个连续数组块的指针。

这种类型之间的区别也可以通过下面的代码来说明:

const char *str1 = "hello";
char str2[6] = "world";
char (*p)[6] = &str2;

/* 指针 str1 加1,指向下一个字符 */
printf("%c\n", *(str1+1));  // e

/* 指针 p 加1,指向下一个数组 */
printf("%c\n", *(*p+1));    // o

从输出结果来看,可以看到这两种类型的指针使用方式是不同的。

int main()
{
	char arr[] = "abcdef";
	printf("%d\n", sizeof(arr));//7   sizeof计算的是数组大小,7*1=6个字节
	printf("%d\n", sizeof(arr + 0));//4/8  arr是首元素的地址,arr+0还是首元素的地址,地址大小是4/8字节
	printf("%d\n", sizeof(*arr));//1   arr是首元素地址,*arr就是首元素,首元素是字符大小是一个字节
	printf("%d\n", sizeof(arr[1]));//1  arr是第二个元素
	printf("%d\n", sizeof(&arr));//4/8   &arr虽然是数组的地址,但还是地址,地址的大小是4/8个字节
	printf("%d\n", sizeof(&arr + 1));//4/8   &arr+1是跳过整个数组后的地址,地址大小是4/8个字节
	printf("%d\n", sizeof(&arr[0] + 1));//4/8   第二个元素的地址

	return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#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));//错误
	//printf("%d\n", strlen(arr[1]));//错误
	printf("%d\n", strlen(&arr));//6   &arr-数组的地址-数组指针char(*p)[7]=&arr;
	printf("%d\n", strlen(&arr + 1));//随机数
	printf("%d\n", strlen(&arr[0] + 1));//5

	return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <string.h>

int main()
{
	char *p = "abcdef";
	printf("%d\n", sizeof(p));//4/8   计算指针变率p的大小
	printf("%d\n", sizeof(p+1));//4/8  p+1得到的是字符b的地址
	printf("%d\n", sizeof(*p));//1   *p就是字符串的第一个字符'a'
	printf("%d\n", sizeof(p[0]));//1   int arr[10]; arr[0]==*(arr+0)   p[0]==*(p+0)=='a'
	printf("%d\n", sizeof(&p));//4/8   地址
	printf("%d\n", sizeof(&p + 1));//4/8   地址
	printf("%d\n", sizeof(&p[0] + 1));//4/8   地址

	return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <string.h>

int main()
{
	char *p = "abcdef";
	printf("%d\n", strlen(p));//6
	printf("%d\n", strlen(p+1));//5
	//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));//5

	return 0;
}

问:指针与数组的转换
ChatAI答:
指针与数组在 C 语言中是密不可分的概念,在很多情况下可以互相转换。

数组可以看做是一个连续的内存空间,在编译时就已经确定了其大小,而指针可以指向这个内存空间的起始地址。

数组名转换为指针
在 C 语言中,数组名代表数组第一个元素的地址,它可以通过自动转换成为同类型指针。所以,在大多数情况下,数组名可以被当作指针来使用。例如:

int a[10];
int *p = a;

上面的代码中,a 是一个数组名,它被自动转换成了 int* 类型的指针,指向 a 数组的首元素,p 指针指向 a 数组的第一个元素。

指针转换为数组名
指针也可以转换为数组名。如果一个指针指向了一个数组的首元素,那么这个指针也可以被当作数组名来使用。例如:

int a[10];
int *p = a;
int (*q)[10] = (int (*)[10])p;

上面的代码中,p 指针指向 a 数组的首元素,再将 p 指针转换为 (int (*)[10]) 类型的指针,可以得到一个指向整个 a 数组的指针。这个指针可以当作数组名使用,例如:

(*q)[0] = 1;     // 修改数组第一个元素的值
printf("%d", a[0]);   // 输出结果为 1

总之,指针与数组之间的转换,可以使得我们在编写代码时具有更大的灵活性。但是,在使用过程中要格外注意指针与数组的类型,防止类型不匹配导致的错误。

自行记忆:星就相当于是[],而&则是可以和星和[]相抵消。(仅限于记忆,三者关系不能完全等价)

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <string.h>

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]));//16   a[0]相当于第一行作为一维数组的数组名,
	//sizeof(arr[0])把数组名单独放在sizeof()内,计算的是第一行的大小
	printf("%d\n", sizeof(a[0] + 1));//4/8   a[0]是第一行的数组名,数组名此时是首元素地址,其实就是第一行第一个元素的地址,
	//所以a[0]+1就是第一行第二个元素的地址,地址大小是4/8个字节
	printf("%d\n", sizeof(*(a[0] + 1)));//4   *(a[0] + 1)是第一行第二个元素,大小是4个字节
	printf("%d\n", sizeof(a+1));//4/8   a是二维数组的数组名,没有sizeof(数组名),也没有&(数组名),所以a是首元素地址,
	//而把二维数组看成一维数组时,二维数组的首元素是他的第一行,a就是第一行(首元素)的地址,a+1就是第二行的地址。
	printf("%d\n", sizeof(*(a+1)));//16   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   a是首元素地址-第一行的地址,*a就是第一行,sizeof(*a)就是计算第一行的大小
	printf("%d\n", sizeof(a[3]));//16   
	return 0;
}
举报

相关推荐

0 条评论