C中sizeof运算符中的参数
我知道当我们对数组名使用C中sizeof运算符中的参数,c,pointers,multidimensional-array,sizeof,C,Pointers,Multidimensional Array,Sizeof,我知道当我们对数组名使用sizeof运算符时,它给出了数组的总大小(以字节为单位)。比如说 int main(int argc, const char * argv[]) { int a[][5] = { {1,2,3,4,5}, {10,20,30,40,50}, {100,200,300,400,500} }; int n=sizeof(a); printf("%d\n",n); } 它将60作为数组的15
sizeof
运算符时,它给出了数组的总大小(以字节为单位)。比如说
int main(int argc, const char * argv[]) {
int a[][5] = {
{1,2,3,4,5},
{10,20,30,40,50},
{100,200,300,400,500}
};
int n=sizeof(a);
printf("%d\n",n);
}
它将60
作为数组的15个元素的输出。但是当我写作的时候
int n=sizeof(*a);
它将20
作为第一行大小的输出,而*a
是0th
行的0th
元素的基址,其类型是指向整数的指针。而a
指向第一行本身。为什么会发生这种情况?
不是指针,它是一个int[5]
,这与您对20
的读取一致,假设一个4字节int
是a
的第0行,该行是一个五个int
的数组
在大多数表达式中,数组会自动转换为指向其第一个元素的指针。因此,当您在语句中使用*a
时,例如int*x=*a代码>,*a
转换为指向其第一个元素的指针。这将导致指向int
的指针,该指针可分配给x
但是,当数组是sizeof
运算符、一元&
运算符或\u Alignof
运算符的操作数时,它不会转换为指向其第一个元素的指针。此外,作为字符串文字用于初始化数组的数组不会转换为指针(因此,在char foo[]=“abc”
中,“abc”
用作数组来初始化foo
;它不会转换为指针)。在这个2d
数组*中,a
是指针,因为当您打印它时,它似乎是一个地址(但它是1st
列地址):
输出:9435248
因此:
当您像这样使用*a
时:*a[3]
其意思是默认情况下您位于第三行和第一列
*a
是1st
列的地址,我们有5
列,因此当您尝试此操作时:
sizeof(*a);
输出将是20
=>(5
column)*(int-pointer
,即4
byte))。Sizeof返回内存中以字节表示的变量大小。这包括填充(编译器向结构中添加未使用的字节以提高性能)。您的数组有15个大小为4的元素。在您的情况下,内存中整数的大小是4。您可以通过运行以下命令轻松验证这一点:
printf("sizeof an integer: %zu\n", sizeof(int));
使用标准的int类型总是一个好主意
#inlcude <stdint.h>
uint32_t a[][5] = {
{1,2,3,4,5},
{10,20,30,40,50},
{100,200,300,400,500}
};
也可以使用宏来执行此操作:
#define ARRAY_LENGTH(array)(sizeof(array)/sizeof(array[0]))
/*ARRAY_LENGTH(a) will return 15 as expected.*/
您也可以在此处查找答案:除非它是sizeof
或一元&
运算符的操作数,或者是用于初始化声明中字符数组的字符串文字,否则类型为“N-element array ofT
”的表达式将转换为(“decay”)类型的表达式“指向T
”的指针,表达式的值将是数组第一个元素的地址
表达式a
的类型为“int
的5元素数组的3元素数组”。因此,a
的大小应产生3*5*sizeof(int)
表达式*a
与表达式a[0]
相同(a[i]
被定义为*(a+i)
-*a
与*(a+0)
相同,这与a[0]
相同。*a
和a[0]
都具有类型为int的“5元素数组”"; 因此,sizeof*a
和sizeof[0]
都应该产生5*sizeof(int)
然而
如果将a
传递给函数,例如
foo( a );
然后a
不是sizeof
或一元&
运算符的操作数,表达式将从类型“int
的5元素数组的3元素数组”转换为“指向int
的5元素数组的指针”:
如果在函数foo
中计算a的sizeof
,则不会得到5*sizeof(int)
,而是会得到sizeof(int(*)[5])
,这取决于平台,将是4到8个字节
类似地,如果将*a
或a[i]
传递给函数,函数实际接收的是指向int
的指针,而不是int
的数组,而sizeof
将反映这一点 二维阵列被视为一维阵列的阵列。也就是说,二维数组中的每一行都是一维数组。对于给定的二维数组a,int a[m][n]
你可以想到
- A[0]作为第0行的地址
- A[1]作为第1行等的地址
解引用可以被认为如下所示:
A[i][j] = *(A[i] + j) = *(*(A+i) + j)
所以当你说*A时,它意味着[0],它给出了第一行的地址,而不是矩阵的第一个元素
- A或*A的解引用给出了第0行或A[0]的地址
- [0]的解引用给出了A或[0][0]的第一个条目,即
**A=A[0][0]
&因为第一行中有5个元素,大小为20字节。@user202729很公平。可能是在sizeof()
的某个地方潜伏了一个副本,它返回的是size\u t
,而不是int
。您可以检查*a的类型。它是int*@GauravMishra如果观察大小对您来说还不够,您可以通过获取其地址并将其存储在另一个变量中来说服自己<代码>整数**p=&*a代码>不会编译,但int(*p)[5]=&*a代码>将。当我编写printf(“%d”,*a)时,编译器会说“Format指定类型'int',但参数的类型为int*”。同时使用&*a时,也会得到变量本身。在这种情况下,您会得到一个指向1d数组的指针类型@这是因为将数组作为参数传递给函数会将其衰减为指向其第一个元素的指针。很抱歉,您没有理解。请
sizeof(a)/sizeof(a[0])
#define ARRAY_LENGTH(array)(sizeof(array)/sizeof(array[0]))
/*ARRAY_LENGTH(a) will return 15 as expected.*/
foo( a );
void foo( int (*a)[5] ) { ... }
A[i][j] = *(A[i] + j) = *(*(A+i) + j)