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 of
T
”的表达式将转换为(“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)