具有可变长度数组类型的 Sizeof 运算符
Sizeof operator with variable-length array type
根据cppreference:
If the type of expression is a variable-length array type, expression
is evaluated and the size of the array it evaluates to is calculated
at run time.
意思是:如果expression的类型是VLA类型,那么expression被求值。例如:
#include <stdio.h>
int main() {
int i = 0;
int a[i];
printf("%zu\n",sizeof(a[i++]));
printf("%d\n",i); // Here, print 0 instead of 1
return 0;
}
所以,根据参考资料,这里的i
变成了1
。但是,使用我的 GCC 编译器,i
打印为 0
.
你例子中sizeof中的表达式是int,不是vla。如果是 vla,一切都会起作用:
#include <stdio.h>
int main() {
int i = 5;
int a[i][i];
printf("%zu\n",sizeof(a[--i]));
printf("%d\n",i); // Here, print 4
return 0;
}
来自 C Standards#6.5.3.4p2 [强调我的]
The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.
表达式中:
sizeof(a[i++])
a[i++]
不是 VLA,而是一个下标运算符表达式,结果是一个整数。因此,操作数未被评估,出于同样的原因,编译器对此语句发出警告:
warning: expression with side effects has no effect in an unevaluated context
取其规范引用的克隆词:
6.5.3.4 - The sizeof and _Alignof operators
The sizeof operator yields the size (in bytes) of its operand, which
may be an expression or the parenthesized name of a type. The size is
determined from the type of the operand. The result is an integer. If
the type of the operand is a variable length array type, the operand
is evaluated; otherwise, the operand is not evaluated and the result
is an integer constant.
它会被评估,如果你修改你的例子来产生一个 VLA 类型的表达式,一种这样的方式
#include <stdio.h>
int main() {
int i = 1;
int a[5][i];
printf("%zu\n",sizeof(a[i++]));
printf("%d\n",i);
return 0;
}
Prints 2
on the last line,因为i
递增。
首先,请注意数组的大小不能为零,无论是否是 VLA。所以你的代码调用了未定义的行为。
C11 6.7.6.2/5
"If the size is an expression that is not an integer constant expression:" /--/ "...each time it is evaluated it shall have a value greater than zero."
至于实际问题,a[i++]
是int
类型,不是VLA类型。
为了得到副作用,必须涉及到VLA数组类型本身,比如sizeof(a)
。只有这样,操作数才会评估副作用。一个例子来说明这一点:
#include <stdio.h>
int main() {
int i=1, j=1;
int a[i][j];
int b[1][1];
(void) sizeof(a[--i]);
(void) sizeof(b[--j]);
printf("%d %d", i, j);
return 0;
}
此处 i
最终为 0,因为第一个 sizeof
由于 VLA 而被评估,但 j
仍然为 1,因为 --j
是 [= 的一部分15=] 对于常规数组。
根据cppreference:
If the type of expression is a variable-length array type, expression is evaluated and the size of the array it evaluates to is calculated at run time.
意思是:如果expression的类型是VLA类型,那么expression被求值。例如:
#include <stdio.h>
int main() {
int i = 0;
int a[i];
printf("%zu\n",sizeof(a[i++]));
printf("%d\n",i); // Here, print 0 instead of 1
return 0;
}
所以,根据参考资料,这里的i
变成了1
。但是,使用我的 GCC 编译器,i
打印为 0
.
你例子中sizeof中的表达式是int,不是vla。如果是 vla,一切都会起作用:
#include <stdio.h>
int main() {
int i = 5;
int a[i][i];
printf("%zu\n",sizeof(a[--i]));
printf("%d\n",i); // Here, print 4
return 0;
}
来自 C Standards#6.5.3.4p2 [强调我的]
The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.
表达式中:
sizeof(a[i++])
a[i++]
不是 VLA,而是一个下标运算符表达式,结果是一个整数。因此,操作数未被评估,出于同样的原因,编译器对此语句发出警告:
warning: expression with side effects has no effect in an unevaluated context
取其规范引用的克隆词:
6.5.3.4 - The sizeof and _Alignof operators
The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.
它会被评估,如果你修改你的例子来产生一个 VLA 类型的表达式,一种这样的方式
#include <stdio.h>
int main() {
int i = 1;
int a[5][i];
printf("%zu\n",sizeof(a[i++]));
printf("%d\n",i);
return 0;
}
Prints 2
on the last line,因为i
递增。
首先,请注意数组的大小不能为零,无论是否是 VLA。所以你的代码调用了未定义的行为。
C11 6.7.6.2/5
"If the size is an expression that is not an integer constant expression:" /--/ "...each time it is evaluated it shall have a value greater than zero."
至于实际问题,a[i++]
是int
类型,不是VLA类型。
为了得到副作用,必须涉及到VLA数组类型本身,比如sizeof(a)
。只有这样,操作数才会评估副作用。一个例子来说明这一点:
#include <stdio.h>
int main() {
int i=1, j=1;
int a[i][j];
int b[1][1];
(void) sizeof(a[--i]);
(void) sizeof(b[--j]);
printf("%d %d", i, j);
return 0;
}
此处 i
最终为 0,因为第一个 sizeof
由于 VLA 而被评估,但 j
仍然为 1,因为 --j
是 [= 的一部分15=] 对于常规数组。