关于长度为1的数组的疑问。

netxuning 2009-02-21 04:34:45
我在openoffice的源代码中看到如下数据结构,是一个unicode字符串结构。
其中的疑问就是,为什么要将存储字符串的buffer定义为 sal_Unicode buffer[1]?
这么定义有什么意义呢?


/** The implementation of a Unicode string.

@internal
*/
typedef struct _rtl_uString
{
sal_Int32 refCount;
sal_Int32 length;
sal_Unicode buffer[1];
} rtl_uString;

...全文
1532 18 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
yueludragon 2009-03-09
  • 打赏
  • 举报
回复
这种情况下,一般需要再额外申请空间的
netxuning 2009-03-09
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 Kevin_zqw 的回复:]
不是应该长度为0吗?

[/Quote]

是啊,c标准不允许的
不过gcc可以
pengzhixi 2009-02-23
  • 打赏
  • 举报
回复
为了空间连续
雨过白鹭洲 2009-02-23
  • 打赏
  • 举报
回复
不是应该长度为0吗?
ch1oE 2009-02-23
  • 打赏
  • 举报
回复
恩,学习了~
yutaooo 2009-02-23
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 netxuning 的回复:]
对了,上边的代码。
str = (string*)malloc(sizeof(string) + (len + 1) * sizeof(char));
这一行,应该不需要 (len + 1)吧?
buffer[1],已经为结尾预留结束符'\0'了?
[/Quote]


_string 中的成员 length 的语意应该是 BUFFER_SIZE, 而不是 STRING_SIZE。对一个字符串来说, BUFFER_SIZE = STRING_SIZE + 1

C 语言中,要求字符串有一个 '\0' 的结尾,是因为无法判断字符串有多长,需要一个‘哨兵’字符用来判断结尾。

这里的 _string 结构没有这样的问题,有 length 成员后,不再需要‘哨兵’了。

当然,这样,就不能使用 strcpy 之类的函数了。应该用自己的专用函数。
lingyin55 2009-02-23
  • 打赏
  • 举报
回复
mark
netxuning 2009-02-23
  • 打赏
  • 举报
回复
对了,上边的代码。
str = (string*)malloc(sizeof(string) + (len + 1) * sizeof(char));
这一行,应该不需要 (len + 1)吧?
buffer[1],已经为结尾预留结束符'\0'了?
netxuning 2009-02-23
  • 打赏
  • 举报
回复
模拟了一个:


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

typedef struct _string string;

struct _string
{
size_t length;
char buffer[1];
};

string *
create_string(const char *s)
{
size_t len = 0;
const char *cp = s;
string *str;

if(s)
while(*cp++) ++len;

str = (string*)malloc(sizeof(string) + (len + 1) * sizeof(char));
str->length = len;
memcpy(str->buffer, s, len);
str->buffer[len] = '\0';

return str;
}

int
main (int c, char **v)
{
if(c < 2)
return;

string *s;
s = create_string(v[1]);
printf("%d %s\n", s->length, s->buffer);
free(s);
}
wjb_yd 2009-02-21
  • 打赏
  • 举报
回复
"变长“结构体
netxuning 2009-02-21
  • 打赏
  • 举报
回复
谢谢楼上几位
我找到了初始化这个结构的代码:



void SAL_CALL rtl_uString_newFromAscii( rtl_uString** ppThis,
const sal_Char* pCharStr )
{
sal_Int32 nLen;

if ( pCharStr )
{
const sal_Char* pTempStr = pCharStr;
while( *pTempStr )
pTempStr++;
nLen = pTempStr-pCharStr;
}
else
nLen = 0;

if ( !nLen )
{
IMPL_RTL_STRINGNAME( new )( ppThis );
return;
}

if ( *ppThis )
IMPL_RTL_STRINGNAME( release )( *ppThis );

*ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nLen );
OSL_ASSERT(*ppThis != NULL);
if ( (*ppThis) )
{
IMPL_RTL_STRCODE* pBuffer = (*ppThis)->buffer;
do
{
/* Check ASCII range */
OSL_ENSURE( ((unsigned char)*pCharStr) <= 127,
"rtl_uString_newFromAscii() - Found ASCII char > 127" );

*pBuffer = *pCharStr;
pBuffer++;
pCharStr++;
}
while ( *pCharStr );
}
}

yutaooo 2009-02-21
  • 打赏
  • 举报
回复

减少 1 次malloc 调用,有道理了。真不错。顶 2 楼的。
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 a_rockboy 的回复:]
好处是申请的空间是与length字段是连续的。。
如果用
typedef struct _rtl_uString
{
sal_Int32 refCount;
sal_Int32 length;
sal_Unicode *buffer;
} rtl_uString;
需要对buffer再次申请空间。
[/Quote]
有道理.
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 a_rockboy 的回复:]
好处是申请的空间是与length字段是连续的。。
如果用
typedef struct _rtl_uString
{
sal_Int32 refCount;
sal_Int32 length;
sal_Unicode *buffer;
} rtl_uString;
需要对buffer再次申请空间。
[/Quote]
有道理.
yutaooo 2009-02-21
  • 打赏
  • 举报
回复

我是这么分析的。

buffer 是一个 unicode 的数组。这里只是为了让 buffer 是一个数组名。

库希望 buffer 数组与 length, refCount 在一个连续的内存空间中。

string 类型当然不可能只有 1 个 unicode 字符。当有多个的时候,可以用如下的代码(这里不考虑对齐的问题,也忽略了异常情况):



_rtl_uString *make_str(int length) {
// int length = 40; 比如需要40个unicode字符。
_rtl_uString *ustr = (_rtl_uString *)malloc(sizeof(sal_Int32) + sizeof(sal_Int32) + length * sizeof(sal_Unicode));
ustr->refCount = 1;
ustr->length = length;

return ustr;
}


当然,这个结构也可以这样设计:


typedef struct _rtl_uString
{
sal_Int32 refCount;
sal_Int32 length;
sal_Unicode *buffer;
} rtl_uString;



但是这样 buffer 数组于 refCount, length 不在连续空间内了。

为啥要连续内存,这个就不清楚了,有什么特别考虑吧。
waizqfor 2009-02-21
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 a_rockboy 的回复:]
好处是申请的空间是与length字段是连续的。。
如果用
typedef struct _rtl_uString
{
sal_Int32 refCount;
sal_Int32 length;
sal_Unicode *buffer;
} rtl_uString;
需要对buffer再次申请空间。
[/Quote]
UP 我感觉也是为了空间连续
a_rockboy 2009-02-21
  • 打赏
  • 举报
回复
好处是申请的空间是与length字段是连续的。。
如果用
typedef struct _rtl_uString
{
sal_Int32 refCount;
sal_Int32 length;
sal_Unicode *buffer;
} rtl_uString;
需要对buffer再次申请空间。
a_rockboy 2009-02-21
  • 打赏
  • 举报
回复
这是不定长字符串。大概意思是这样:

rtl_uString * str = malloc(256);
str->length = 256;
str->buffer现在就指向一个长度为256 - 8的缓冲区。

strcpy(str->buffer, ....);

一般用在相对底层的代码,可以管理字符串的长度,引用次数等。

70,018

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧