填充在C中作为参数传递的预先分配的固定大小的字符串

时间:2021-12-30 21:44:55

I need to get a fixed length name from a 3rd party developer in a clean way that (hopefully) doesn't require any allocation on their side, and is checked well by the compiler.

我需要以一种干净的方式从第三方开发者那里获得一个固定长度的名称(希望)不需要任何分配,并且编译器会对其进行检查。

I provide a prototype like this:

我提供这样的原型:

void getName(char name[9]);

And they would write a function something like this:

他们会写一个像这样的函数:

void getName(char name[9]) {
   strncat(_name, "Hello World", 8);
}

Then I call it (on my side) sort of like this:

然后我称它(在我身边)有点像这样:

char buf[9];
*buf = '\0';
getName(buf);
doSomethingWith(buf);

It compiles and seems to work, but I'm not sure its the best way to handle this.

它编译并似乎工作,但我不确定它是处理这个的最佳方法。

Any advice?

任何建议?

Edit: To clarify, the name string is used as an identifier in a packed binary save file. It needs to be exactly 8 ASCII 8-bit chars.

编辑:为了澄清,名称字符串用作打包二进制保存文件中的标识符。它需要恰好是8个ASCII 8位字符。

I wonder now if I should just receive any string and truncate it on my side. I was hoping the compiler would help instead of this being a runtime check.

我现在想知道我是否应该收到任何字符串并将其截断在我身边。我希望编译器能帮助,而不是运行时检查。

2 个解决方案

#1


2  

In your example, the name is a static string. In this case the function could look like below, where no additional data copy is required:

在您的示例中,名称是静态字符串。在这种情况下,该函数可能如下所示,其中不需要额外的数据副本:

const char* getName(void)
{
    return "Hello World";
}

...

...

const char* const pName = getName();

Alternatively:

或者:

void getName(FUNCPTR func)
{
    func("Hello World");
}

where the void func(const char* const pName) is implemented at your side. Then you also don't need to allocate/copy data.

其中void func(const char * const pName)在你身边实现。那么您也不需要分配/复制数据。

#2


0  

Your first job is to agree the data type of the returned string.

您的第一个工作是同意返回字符串的数据类型。

Although it's tempting to use char*, you ought not to since the type of char is not sufficiently well-defined by the standard (could be unsigned, signed 2's complement or signed 1's complement). If you're not careful the behaviour of your program could be undefiend if you mix up your types. So you ought to decide on a type and use #DEFINE CharType accordingly.

尽管使用char *很有吸引力,但是你不应该因为标准没有充分定义char的类型(可以是unsigned,signed 2的补码或者1的补码)。如果你不小心,如果你混淆你的类型,你的程序的行为可能是不可取的。所以你应该决定一个类型并相应地使用#DEFINE CharType。

Then as for the function itself, don't rely on the 3rd party to allocate memory unless you call their library to release that memory. Your C runtime might use a different allocation system to theirs. In order to address this common issue, a sort of convention has grown up: if you pass NULL for the output buffer then the 3rd party function should return the length of the buffer required. Then you allocate the memory yourself with the required length, and call the function a second time with the size of the allocated buffer explicitly sent. In that mode, the function returns the length of the allocated string as well as the result populated into the buffer.

至于函数本身,除非你调用它们的库释放那个内存,否则不要依赖第三方来分配内存。您的C运行时可能会使用不同的分配系统。为了解决这个常见问题,一种惯例已经成长:如果为输出缓冲区传递NULL,那么第三方函数应该返回所需缓冲区的长度。然后,您自己使用所需的长度分配内存,并第二次调用该函数,并显式发送分配的缓冲区的大小。在该模式下,该函数返回已分配字符串的长度以及填充到缓冲区中的结果。

Putting this all together, a good prototype would be

把这一切放在一起,一个好的原型将是

SizeType getName(CharType* buffer, SizeType length);

SizeType getName(CharType * buffer,SizeType length);

where SizeType is again agreed upon between you and the 3rd party. Broadly speaking, this is how the Windows API works.

其中SizeType再次与您和第三方达成一致。从广义上讲,这就是Windows API的工作原理。

#1


2  

In your example, the name is a static string. In this case the function could look like below, where no additional data copy is required:

在您的示例中,名称是静态字符串。在这种情况下,该函数可能如下所示,其中不需要额外的数据副本:

const char* getName(void)
{
    return "Hello World";
}

...

...

const char* const pName = getName();

Alternatively:

或者:

void getName(FUNCPTR func)
{
    func("Hello World");
}

where the void func(const char* const pName) is implemented at your side. Then you also don't need to allocate/copy data.

其中void func(const char * const pName)在你身边实现。那么您也不需要分配/复制数据。

#2


0  

Your first job is to agree the data type of the returned string.

您的第一个工作是同意返回字符串的数据类型。

Although it's tempting to use char*, you ought not to since the type of char is not sufficiently well-defined by the standard (could be unsigned, signed 2's complement or signed 1's complement). If you're not careful the behaviour of your program could be undefiend if you mix up your types. So you ought to decide on a type and use #DEFINE CharType accordingly.

尽管使用char *很有吸引力,但是你不应该因为标准没有充分定义char的类型(可以是unsigned,signed 2的补码或者1的补码)。如果你不小心,如果你混淆你的类型,你的程序的行为可能是不可取的。所以你应该决定一个类型并相应地使用#DEFINE CharType。

Then as for the function itself, don't rely on the 3rd party to allocate memory unless you call their library to release that memory. Your C runtime might use a different allocation system to theirs. In order to address this common issue, a sort of convention has grown up: if you pass NULL for the output buffer then the 3rd party function should return the length of the buffer required. Then you allocate the memory yourself with the required length, and call the function a second time with the size of the allocated buffer explicitly sent. In that mode, the function returns the length of the allocated string as well as the result populated into the buffer.

至于函数本身,除非你调用它们的库释放那个内存,否则不要依赖第三方来分配内存。您的C运行时可能会使用不同的分配系统。为了解决这个常见问题,一种惯例已经成长:如果为输出缓冲区传递NULL,那么第三方函数应该返回所需缓冲区的长度。然后,您自己使用所需的长度分配内存,并第二次调用该函数,并显式发送分配的缓冲区的大小。在该模式下,该函数返回已分配字符串的长度以及填充到缓冲区中的结果。

Putting this all together, a good prototype would be

把这一切放在一起,一个好的原型将是

SizeType getName(CharType* buffer, SizeType length);

SizeType getName(CharType * buffer,SizeType length);

where SizeType is again agreed upon between you and the 3rd party. Broadly speaking, this is how the Windows API works.

其中SizeType再次与您和第三方达成一致。从广义上讲,这就是Windows API的工作原理。