【问题标题】:sizeof evaluation of a variable-length array可变长度数组的 sizeof 评估
【发布时间】:2015-11-12 07:46:00
【问题描述】:

sizeof 操作数将计算操作数,如果它是一个变长数组。

6.5.3.4、p2:如果操作数的类型是变长数组类型,则对操作数求值;

但这段代码正在运行,我假设它已定义:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

struct test
{
    struct test* t;
    int i;  
};

int main(void) 
{
    int r = ( rand() % 100 ) + 1;
    assert( r > 0 );
    struct test* a[r];
    for( size_t i = 0; i < r; i++ )
    {
        a[i] = NULL;
    }

    printf("%zu\n" , sizeof( a[0]->i ) );
    //printf("%d\n", a[0]->i ); //this will of course crash the program

    return 0;
}
  1. 代码定义了吗?
  2. 是否评估了 sizeof 操作数?
  3. 评估不应该取消对指针的引用吗?
  4. 根据上下文,第一个和第二个printf 有什么区别?

该程序似乎是正确的,有任何额外的尊重:

struct other
{
    int i;  
};

struct test
{
    struct other* t; 
};

int main(void) 
{
    int r = ( rand() % 100 ) + 1;
    assert( r > 0 );
    struct test* a[r];
    for( size_t i = 0; i < r; i++ )
    {
        a[i] = NULL;
    }

    printf("%zu\n" , sizeof( a[0]->t->i ) );
    //printf("%d\n", a[0]->t->i ); //this will of course crash the program

    return 0;
}

【问题讨论】:

标签: c language-lawyer c99 c11 variable-length-array


【解决方案1】:

a 本身就是一个 VLA。但是a[0]-&gt;i不是,它的类型是int

所以sizeof( a[0]-&gt;i ) 就是sizeof(int)sizeof 这里是编译时操作符,a[0]-&gt;i 不求值,代码已定义。

【讨论】:

  • 你认为用sizeof和VLA有可能引起ub吗?
【解决方案2】:

的操作数
sizeof a[0]->i

不是 VLA,因此不被评估。两者都不会

sizeof a[0]

只有类似的结构

sizeof a

需要在运行时评估它的参数,因为该动物的大小在编译时是未知的。

编辑: 当然,这样的评估可能是错误的。如果你有

double (*p)[n];

所以一个指向 VLA 的指针。那么

sizeof *p

是一个运行时表达式,如果您没有正确初始化 p,则会出现错误。

【讨论】:

  • 你认为用sizeof和VLA有可能引起ub吗?
  • @this,你不能“导致”UB,未定义的行为不是行为,而是根据定义没有它。如果您询问被评估的表达式是否可能是错误的,是的,当然。只需将p 用作指向VLA 的指针并执行sizeof *p。如果 p0 这将使您的程序崩溃。
  • 我已经尝试了好几次,但程序运行正常。也许我应该作为一个新问题。我希望你不介意我是否链接到这个答案?
  • 我应该说“可能会使您的程序崩溃”。没有定义行为的错误代码的问题在于它可以做任何事情,甚至看起来可以工作。那你就靠自己了。
  • 我知道,我没有说代码是定义的。我也知道什么是ub。仍然很奇怪,因为显然在这种情况下 sizeof 的评估方式与将崩溃的普通指针取消引用相同。那么为什么会有差异。
猜你喜欢
  • 2018-03-10
  • 1970-01-01
  • 1970-01-01
  • 2013-02-06
  • 2018-07-17
  • 2015-12-18
  • 2011-12-08
  • 2012-01-04
相关资源
最近更新 更多