首页 > 其他分享 >C语言-数组名与&数组名的细节注意

C语言-数组名与&数组名的细节注意

时间:2024-08-23 08:57:27浏览次数:7  
标签:arr 细节 C语言 数组名 数组 printf sizeof strlen

这篇博客将通过整型数组、字符数组、字符串放在数组中、以及二维数组的数组名与&数组名和各类特殊情况的题目讲解来使得我们对于指针与数组名具有更加深刻的了解。

注意:

sizeof(数组名) - 数组名表示整个数组的-计算的是整个数组的大小
&数组名 - 数组名表示整个数组,取出的是整个数组的地址
除此之外,所有的数组名都是数组首元素的地址 !!!


1.整型数组

//sizeof(数组名) - 数组名表示整个数组的-计算的是整个数组的大小
//&数组名 - 数组名表示整个数组,取出的是整个数组的地址
//除此之外,所有的数组名都是数组首元素的地址
int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));//16 - sizeof(数组名),计算的是整个数组的大小因此结果为:16
printf("%d\n",sizeof(a+0));//4/8 - 不是数组名,因此表示的是数组首元素的地址的大小
                           //因此64位平台是8,32位平台是4
printf("%d\n",sizeof(*a));//4 - a表示首元素的地址解引用访问的一个元素int
printf("%d\n",sizeof(a+1));//4/8 - 表示的是数组第一个元素的地址的大小
printf("%d\n",sizeof(a[1]));//4 - 第二个元素的大小

printf("%d\n",sizeof(&a));//4/8 - &a虽然数组的地址,但是也是地址,sizeof (&a)计算的是一个地址的大小
printf("%d\n",sizeof(*&a));//16 - 计算的数组的大小
printf("%d\n",sizeof(&a+1));//4/8 - &a + 是数组后面的空间的地址
printf("%d\n",sizeof(&a[0]));//4/8 - 第一个元素的地址的大小
printf("%d\n",sizeof(&a[0]+1));//4/8 - 第二个元素的地址的大小


2.字符数组 

char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));//6
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

printf("%d\n", strlen(arr));//随机值 - strlen是找'\0',而此时数组里面没有存放'\0',必然会访 
                            //问数组后面的内容
printf("%d\n", strlen(arr + 0));//随机值
printf("%d\n", strlen((const char*) *arr));//err
printf("%d\n", strlen((const char*) arr[1]));//err
printf("%d\n", strlen((const char*) &arr));//随机值
printf("%d\n", strlen((const char*) (&arr + 1)));//随机值-6
printf("%d\n", strlen(&arr[0] + 1));//随机值-1

printf("%d\n", strlen((const char*) *arr)); //err

printf("%d\n", strlen((const char*) arr[1]));//err

 

*arr找到了数组中的'a',而'a'的Ascll码表值是97,而strlen函数会把97看成地址,97的16进制便是0x00000061,便出现如上图所示的错误。arr[1]也是同样的道理


3.字符串放在数组中

char arr[] = "abcdef";
printf("%d\n", sizeof(arr));//7,该种方式数组里面存放的是:[a b c d e f \0]
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

printf("%d\n", strlen(arr));//6 [a b c d e f \0]
printf("%d\n", strlen(arr+0));//6
printf("%d\n", strlen(*arr));//err
printf("%d\n", strlen(arr[1]));//err
printf("%d\n", strlen((const char*) &arr));//6
printf("%d\n", strlen((const char*) (&arr+1)));//随机值
printf("%d\n", strlen(&arr[0]+1));//5

char *p = "abcdef";//这是把a的地址放在了指针变量p中
 printf("%d\n", sizeof(p));//4/8
 printf("%d\n", sizeof(p+1));//4/8
 printf("%d\n", sizeof(*p));//1
 printf("%d\n", sizeof(p[0]));//1
 printf("%d\n", sizeof(&p));//4/8
 printf("%d\n", sizeof(&p+1));//4/8
 printf("%d\n", sizeof(&p[0]+1));//4/8

 printf("%d\n", strlen(p));//6
 printf("%d\n", strlen(p+1));//5
 printf("%d\n", strlen(*p));//err
 printf("%d\n", strlen(p[0]));//err
 printf("%d\n", strlen(&p));//随机
 printf("%d\n", strlen(&p+1));//随机
 printf("%d\n", strlen(&p[0]+1));//5

 我们不但要知道结果是什么更应该知道它所对应的空间及其地址,如下所示:

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

 printf("%d\n", strlen(&p));//随机
 printf("%d\n", strlen(&p+1));//随机

 这两个随机值不存在联系,因为P中所存放的地址不确定,如:0x11223344,那这两个随机值便差了四个字节,但如果是0x11220044,\0在地址中出现那么&P便是两个字节,所以这两个随机值不存在必然的联系。


 4.二维数组

int a[3][4] = {0};
 printf("%d\n",sizeof(a));//48 - 数组名放在sizeof内部表示整个数组,因此3*4*4=48
 printf("%d\n",sizeof(a[0][0]));//4
 printf("%d\n",sizeof(a[0]));//16 - a[0]可以看成二维数组中的第一行的“一维数组”的数组名
                             //因此也便是第一行的“一维数组”的数组名放在了sizeof内部
 printf("%d\n",sizeof(a[0]+1));//4/8 - a[0]+1是二维数组中的第一行的第二个元素的地址
 printf("%d\n",sizeof(*(a[0]+1)));//4 - 计算的是a[0]+1是二维数组中的第一行的第二个元素的大小
 printf("%d\n",sizeof(a+1));//4/8 - a表示二维数组的首元素地址,即第一行的“一维数组”的地址
                            //则a+1表示第二行的“一维数组”的地址
 printf("%d\n",sizeof(*(a+1)));//16 - 计算的是第二行的“一维数组”的大小
 printf("%d\n",sizeof(&a[0]+1));//4/8 - &a[0]取出的是二维数组中的第一行的“一维数组”的地址
                                //则&a[0]+1表示第二行的“一维数组”的地址
 printf("%d\n",sizeof(*(&a[0]+1)));//16 - 计算的是第二行的“一维数组”的大小
 printf("%d\n",sizeof(*a));//16 - 第一行的“一维数组”的大小
 printf("%d\n",sizeof(a[3]));//16 - a[3]其实是第四行的数组名 (如果有的话)
                             //所以其实不存在,也能通过类型计算大小的

在上述二维数组中比较难以理解的便是 a[0] 、 a+1 、&a[0]+1 、a[3],下面对其进行讲解:

对于二维数组如果把每一行都看作成一个一维数组那么a[0]就可以看作成一维数组的数组名,所以a[0]在sizeof(数组名)与&数组名情况之外下表示的是第一行的首元素的地址,&a[0]也就是取出的是第一行的一维数组的地址。

对a这个二维数组的数组名,它依然在sizeof(数组名)与&数组名情况之外下就表示首元素的地址,但是对于二维数组数组名所表示的首元素就是第一行。

对于a[3],这一空间随超出了我们所定义的二维数组的空间,但是sizeof内部是不参与运算的,因此也便不会产生越界访问的情况,至于16的计算是因为,sizeof所计算的是类属性,是按照一维数组的属性进行计算。

标签:arr,细节,C语言,数组名,数组,printf,sizeof,strlen
From: https://blog.csdn.net/qq_53706413/article/details/141332878

相关文章

  • C++模板的细节改进
    emsp;emsp;C++11改进了编译器的解析规则,尽可能的将多个右尖括号(>)解析称模板参数结束符,方便我们编写模板相关的代码。1.模板的右尖括号emsp;emsp;在C++98/03的泛型编程中,模板实例化有一个很繁琐的地方,那就是连续两个右尖括号(>>)会被变异器解释称右移操作符,而不是模板参数表的结束......
  • 自学C语言
    DAY#0一开始(好好学习,提前内卷!)后面……什么鬼,电子信息工程到底是什么,我要学什么然后#宋浩高数#,#每日英语#学着学着劲头就没了,啊啊啊小说我来了》~《然后又是浑浊,挣扎最近加入了校园的科协预备群,www,一下子感觉亚历山大了(因为看过学长分享,非常想进去,他高一就是进了科协)要学的......
  • 自学C语言
    DAY#3哎,今天忙了很多事,晚上九点才碰到电脑。没什么时间学电脑,又补了一点电脑常识,关于文件还有C盘的一些常识(C盘真的非常非常重要!!)早上弄了校园卡(大学真是个神奇的东西)下午忙忙忙,晚上又学了一点基础知识。和家人发生了矛盾,我好难过/-||||DAY#4(啊啊啊啊,昨天的怎么没有发送......
  • C语言常见概念
    1.编译器1.1编译和链接C语言是一门编译型计算机语言,C语言源代码是文本文件,文本文件本身无法执行,必须通过编译器翻译和链接器的链接,生成二进制的可执行文件,可执行文件才能执行。C语言代码放在.c为后缀的文件中,经过编译和链接2个过程,才能得到可执行程序。•每个源文件(.c)......
  • C语言的语句分类
    C语言的代码是由一条条语句构成的,可分为五类:空语句一个分号就是一个语句,即空语句,一般出现的地方是:这里需要一条语句,但这个语句不需要做任何事。表达式语句在表达式的后面加上分号,构成表达式语句。函数调用语句复合语句成对括号中的代码构成一个代码块,也称复合语句。控......
  • C语言基础--数组详解
    目录数组的概述1数组的概念2数组的分类一维数组1一维数组的定义2数组的访问3数组元素的初始值3.1先定义,后设置值3.2定义同时设置初始值3.2.1全部设置初始值3.2.2部分设置初始值4一维数组的应用实例5一维字符数组5.1一维字符数组的定义5.2一维字符......
  • C语言数据类型和变量(下)
    目录1.算数操作符:+、-、*、/、%1.1+和-1.2*5.3/5.4%2.赋值操作符:=和复合赋值2.1连续赋值6.2复合赋值符3.单目操作符:++、--、+、-3.1++和--3.1.1前置++3.1.2后置++3.1.3前置--3.1.4后置-- 3.2+和- 4.强制类型转换 5.scanf和prin......
  • 03.C语言学习【零基础版】@CHX------算术操作符
    一.+and-+:加法-:减法代码:#include<stdio.h>intmain(){ inta=5+7; intb=20-44; printf("%d%d\n",a,b); return0;}运行结果:二.* *:乘法代码:#include<stdio.h>intmain(){ inta=5+7; intb=20-18; printf("%d\n"......
  • 【C语言进阶】数据如何安家?C语言内存中的存储艺术深度解析
    ......
  • C语言学习,预处理器
    C预处理器不是编译器的一部分,是编译过程中的一个单独步骤。C预处理器是一个文本替换工具,它指示编译器在编译前进行必要的预处理。 C预处理器所有命令都以井号(#)开头,它必须是第一个非空白字符,以下列出了重要的预处理程序指令:No.指令和说明1#define替换预处理器宏。2#inc......