我来我网
https://5come5.cn
 
您尚未 登录  注册 | 菠菜 | 软件站 | 音乐站 | 邮箱1 | 邮箱2 | 风格选择 | 更多 » 
 

本页主题: 变量长度数组 显示签名 | 打印 | 加为IE收藏 | 收藏主题 | 上一主题 | 下一主题

ljpdxj



性别: 帅哥 状态: 该用户目前不在线
等级: 栋梁之材
发贴: 687
威望: 0
浮云: 1108
在线等级:
注册时间: 2006-02-28
最后登陆: 2008-06-29

5come5帮你背单词 [ bone /bəun/ n. 骨头,骨状物 ]


变量长度数组

最近细读《Programming in C》,里面讲数组时讲到了“变量长度数组”,说有的编译器支持这样的用法:

      int i=10;
      char buf[ i ];

      我测试发现VC6是不支持这个的,但是GCC支持!我写了这样的测试代码,发现程序居然也支持i是负数,而且在负数的情况下,GCC的内存分配虽然怪异,但也是保证正确的。

Copy code
#include <stdlib.h>
#include <stdio.h>

void fun(int i)
{
    char kk = 'B';
    char buf[ i ];
    char mm = 'E';

    printf("size :: %d %x -- %x\n", sizeof(buf), (size_t)buf, (size_t)&buf[i-1]);
    buf[i-1] = 'a';
    printf("\t\t\t buf[i-1]:%c\t %x:%c \t %x:%c \n", buf[i-1], (size_t)&kk, kk, (size_t)&mm, mm);
}

int main(int argc, char * argv[], char * envp[])
{
    fun(2);
    fun(3);
    fun(4);
    fun(1);
    fun(0);
    fun(-1);
    fun(-10);
}

GCC安全的为负数长度的数组分配了空间,保证了这种数组的安全使用, 不会影响栈上的其他变量空间。
下面是输出:

Copy code

size :: 2 bfbfec50 -- bfbfec51
                        buf[i-1]:a      bfbfec7f:B      bfbfec7e:E
size :: 3 bfbfec50 -- bfbfec52
                        buf[i-1]:a      bfbfec7f:B      bfbfec7e:E
size :: 4 bfbfec50 -- bfbfec53
                        buf[i-1]:a      bfbfec7f:B      bfbfec7e:E
size :: 1 bfbfec60 -- bfbfec60
                        buf[i-1]:a      bfbfec7f:B      bfbfec7e:E
size :: 0 bfbfec60 -- bfbfec5f
                        buf[i-1]:a      bfbfec7f:B      bfbfec7e:E
size :: -1 bfbfec60 -- bfbfec5e
                        buf[i-1]:a      bfbfec7f:B      bfbfec7e:E
size :: -10 bfbfec60 -- bfbfec55
                        buf[i-1]:      bfbfec7f:B      bfbfec7e:E

我的疑问:




0长度的数组有什么意义?
这个经过搜索资料,我已经知道了,参考:http://bbs.chinaunix.net/viewthread.php?tid=854949

在产品级的软件开发中,这种“变量长度数组”有人应用吗?
嗯,我估计这种不通用的东西产品里应该很少用。尽量避免使用,增强移植性。

至于数组长度是负数的情况,我是这么想的:
      GCC就像数学家发现自然数后又发现了负数那样,GCC为人们实现了负数数组长度,并告诉我们数组长度也可以是负数。
      至于负数有什么物理意义,数学家先不管了;数组长度负数有什么实际意义,Gcc就不管了。

Quote:
引用第1楼yinx于2007-11-30 12:36发表的  :
变量mm的空间分配先于buf数组?
能对0长度数组或者负数长度数组的单元赋值吗?

风中帖的转过来
回答第一个问题:我也不太清楚mm的空间分配是否先于buf,但是肯定的是在程序运行的时候分配,变量长度数组C99是不支持的,但是有些编译器支持如GCC;在标准 C 或者 C++ 中由于不支持 0 长度的数组,所以 int array[0]; 这样的定义是非法的。不过有些编译器的扩展功能支持 0 长度的数组。声明0长度数组也只是做一个地址标记。
第二个问题:从上面测试代码来看很明显如果用GCC, 0长度数组或者负数长度数组的单元赋值是成功的,但内存单元具体怎么实现不清楚

在 C 中,0 长度的数组的主要用途是用来作为结构体的最后一个成员,然后用它来访问此结构体对象之后的一段内存(通常是动态分配的内存)。由于其非标准性,在程序中尽量避免使用 0 长度的数组。作为替换,可以使用 C99 标准中的不完整数组来替换 0 长度的数组定义。
在工程中0长度数组:
Copy code
int main(void)
{
    struct  student{
            unsigned int ID;
            char  follow_info[0];
            /*这里不能再有数据成员*/
        } Ptr*;
  int i = 100 ,count ;
    Ptr = malloc(sizeof(struct student) + i);
    for (count =0 ; count < i; ++count )
        p->data[i] = 1;
}



[ 此帖被ljpdxj在2007-11-30 14:53重新编辑 ]
顶端 Posted: 2007-11-29 22:49 | [楼 主]
lxlcn



性别: 帅哥 状态: 该用户目前不在线
等级: 鹤立鸡群
发贴: 1310
威望: 0
浮云: 1741
在线等级:
注册时间: 2005-10-06
最后登陆: 2011-06-29

5come5帮你背单词 [ pen /pen/ n. 钢笔 ]


与“变量长度数组”差不多等效的方法叫malloc吧
一个在栈中分配,另一个在堆中.
手动在栈中分配的内存是不安全的,估计是这个原因有的编译器不让这样做..
不过真的一直没有思考过关于参数为负的数组的问题长见识了 
顶端 Posted: 2007-11-29 23:15 | [1 楼]
依然随意



性别: 帅哥 状态: 该用户目前不在线
等级: 前途无量
家族: ⊙JAY菊爱园⊙
发贴: 5922
威望: 0
浮云: 760
在线等级:
注册时间: 2006-09-25
最后登陆: 2022-10-30

5come5帮你背单词 [ wax /wæks/ n. 蜡,蜂蜡;vt. 给…上蜡 ]


      int i=10;
      char buf[ i ];这种分配静态内存的方法还可以理解,编译器可以预处理嘛,
但是
void fun(int i)
{
    char kk = 'B';
    char buf[ i ];
    。。。。。
}这种分配静态区的方法还是第一次见过,真的很诡异。
顶端 Posted: 2007-11-30 09:54 | [2 楼]
hhbhhb



性别: 帅哥 状态: 该用户目前不在线
等级: 品行端正
发贴: 292
威望: 0
浮云: 1105
在线等级:
注册时间: 2006-09-21
最后登陆: 2009-03-16

5come5帮你背单词 [ central /'sentrəl/ a. 中心的,中央的,主要的,首要的 ]


其实从汇编来考虑的话也确实是可以实现的。。只要被调用函数清栈,过程中占了多少栈空间确实无所谓嘛。。
顶端 Posted: 2007-11-30 10:41 | [3 楼]
zhd32



性别: 帅哥 状态: 该用户目前不在线
等级: 版主
家族: YD一族
发贴: 619
威望: 0
浮云: 543
在线等级:
注册时间: 2006-04-22
最后登陆: 2009-06-22

5come5帮你背单词 [ gasoline /'gæsəli:n/ n. (美语)汽油 ]


Quote:
引用第3楼hhbhhb于2007-11-30 10:41发表的  :
其实从汇编来考虑的话也确实是可以实现的。。只要被调用函数清栈,过程中占了多少栈空间确实无所谓嘛。。

汇编是无所不能的~~
顶端 Posted: 2007-11-30 11:56 | [4 楼]
ljpdxj



性别: 帅哥 状态: 该用户目前不在线
等级: 栋梁之材
发贴: 687
威望: 0
浮云: 1108
在线等级:
注册时间: 2006-02-28
最后登陆: 2008-06-29

5come5帮你背单词 [ sunny /'sΛni/ a. 阳光充足的 ]


Quote:
引用第1楼yinx于2007-11-30 12:36发表的  :
变量mm的空间分配先于buf数组?
能对0长度数组或者负数长度数组的单元赋值吗?

风中帖的转过来
回答第一个问题:我也不太清楚mm的空间分配是否先于buf,但是肯定的是在程序运行的时候分配,变量长度数组C99是不支持的,但是有些编译器支持如GCC;在标准 C 或者 C++ 中由于不支持 0 长度的数组,所以 int array[0]; 这样的定义是非法的。不过有些编译器的扩展功能支持 0 长度的数组。声明0长度数组也只是做一个地址标记。
第二个问题:从上面测试代码来看很明显如果用GCC, 0长度数组或者负数长度数组的单元赋值是成功的,但内存单元具体怎么实现不清楚

在 C 中,0 长度的数组的主要用途是用来作为结构体的最后一个成员,然后用它来访问此结构体对象之后的一段内存(通常是动态分配的内存)。由于其非标准性,在程序中尽量避免使用 0 长度的数组。作为替换,可以使用 C99 标准中的不完整数组来替换 0 长度的数组定义。
在工程中0长度数组:
Copy code
int main(void)
{
    struct  student{
            unsigned int ID;
            char  follow_info[0];
            /*这里不能再有数据成员*/
        } Ptr*;
  int i = 100 ,count ;
    Ptr = malloc(sizeof(struct student) + i);
    for (count =0 ; count < i; ++count )
        p->data[i] = 1;
}



[ 此帖被ljpdxj在2007-11-30 14:52重新编辑 ]
顶端 Posted: 2007-11-30 14:41 | [5 楼]
我来我网·5come5 Forum » 程序员之家

Total 0.022965(s) query 5, Time now is:11-22 16:10, Gzip enabled
Powered by PHPWind v5.3, Localized by 5come5 Tech Team, 黔ICP备16009856号