如何在不使用变量 C/C++ 的情况下将常量数组文字传递给采用指针的函数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1269568/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to pass a constant array literal to a function that takes a pointer without using a variable C/C++?
提问by sinoth
If I have a prototype that looks like this:
如果我有一个看起来像这样的原型:
function(float,float,float,float)
I can pass values like this:
我可以传递这样的值:
function(1,2,3,4);
So if my prototype is this:
所以如果我的原型是这样的:
function(float*);
Is there any way I can achieve something like this?
有什么办法可以实现这样的目标吗?
function( {1,2,3,4} );
Just looking for a lazy way to do this without creating a temporary variable, but I can't seem to nail the syntax.
只是寻找一种懒惰的方法来做到这一点而不创建临时变量,但我似乎无法确定语法。
回答by Adam Rosenfield
You can do it in C99 (but notANSI C (C90) or any current variant of C++) with compound literals. See section 6.5.2.5 of the C99 standard for the gory details. Here's an example:
您可以在 C99(但不是ANSI C (C90) 或 C++ 的任何当前变体)中使用复合文字来实现。有关详细信息,请参阅 C99 标准的第 6.5.2.5 节。下面是一个例子:
// f is a static array of at least 4 floats
void foo(float f[static 4])
{
...
}
int main(void)
{
foo((float[4]){1.0f, 2.0f, 3.0f, 4.0f}); // OK
foo((float[5]){1.0f, 2.0f, 3.0f, 4.0f, 5.0f}); // also OK, fifth element is ignored
foo((float[3]){1.0f, 2.0f, 3.0f}); // error, although the GCC doesn't complain
return 0;
}
GCC also provides this as an extension to C90. If you compile with -std=gnu90
(the default), -std=c99
, or -std=gnu99
, it will compile; if you compile with -std=c90
, it will not.
GCC 还提供了它作为 C90 的扩展。如果您使用-std=gnu90
(默认值)、-std=c99
、 或 进行-std=gnu99
编译,它将编译;如果你用 编译-std=c90
,它不会。
回答by GManNickG
This is marked both C and C++, so you're gonna get radically different answers.
这被标记为 C 和 C++,所以你会得到完全不同的答案。
If you are expecting four parameters, you can do this:
如果您需要四个参数,您可以这样做:
void foo(float f[])
{
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
float f[] = {1, 2, 3, 4};
foo(f);
}
But that is rather unsafe, as you could do this by accident:
但这相当不安全,因为您可能会不小心这样做:
void foo(float f[])
{
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
float f[] = {1, 2}; // uh-oh
foo(f);
}
It is usually best to leave them as individual parameters. Since you shouldn't be using raw arrays anyway, you can do this:
通常最好将它们作为单独的参数。由于您无论如何都不应该使用原始数组,您可以这样做:
#include <cassert>
#include <vector>
void foo(std::vector<float> f)
{
assert(f.size() == 4);
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
float f[] = {1, 2, 3, 4};
foo(std::vector<float>(f, f + 4)); // be explicit about size
// assert says you cannot do this:
foo(std::vector<float>(f, f + 2));
}
An improvement, but not much of one. You could use boost::array
, but rather than an error for mismatched size, they are initialized to 0:
一种改进,但不是很大。您可以使用boost::array
,但不是大小不匹配的错误,而是将它们初始化为 0:
#include <boost/array.hpp>
void foo(boost::array<float, 4> f)
{
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
boost::array<float, 4> f = {1, 2, 3, 4};
foo(f);
boost::array<float, 4> f2 = {1, 2}; // same as = {1, 2, 0, 0}
foo(f2);
}
This will all be fixed in C++0x, when initializer list constructors are added:
当添加初始化列表构造函数时,这将在 C++0x 中全部修复:
#include <cassert>
#include <vector>
void foo(std::vector<float> f)
{
assert(f.size() == 4);
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
foo({1, 2, 3, 4}); // yay, construct vector from this
// assert says you cannot do this:
foo({1, 2});
}
And probably boost::array
as well:
也可能boost::array
是:
#include <boost/array.hpp>
void foo(boost::array<float, 4> f)
{
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
foo({1, 2, 3, 4});
foo({1, 2}); // same as = {1, 2, 0, 0} ..? I'm not sure,
// I don't know if they will do the check, if possible.
}
回答by ezpz
You can create a compound literal:
您可以创建复合文字:
function ((float[2]){2.0, 4.0});
Although, I'm not sure why you want to go through the trouble. This is not permitted by ISO.
虽然,我不确定你为什么要经历这些麻烦。这是 ISO 不允许的。
Generally, shortcuts like this should be avoided in favor of readability in all cases; laziness is not a good habit to explore (personal opinion, of course)
一般来说,应该避免这样的快捷方式,以便在所有情况下都具有可读性;懒惰不是探索的好习惯(当然是个人意见)
回答by Eugene
You can technically take reference to array, but you still can't create anonymous initializer list I think.
从技术上讲,您可以参考数组,但我认为您仍然无法创建匿名初始值设定项列表。
void func(int (&bla)[4])
{
int count = sizeof(bla)/sizeof(bla[0]);
// count == 4
}
int bla[] = {1, 2, 3, 4};
func(bla);
int bla1[] = {1, 2};
func(bla1); // <-- fails
For C++ way, look at boost::assign. Pretty neat way of filling in STL containers.
对于 C++ 方式,请查看boost::assign。填充 STL 容器的非常简洁的方式。
回答by Peter Ruderman
The bad news is that there is no syntax for that. The good news is that this will change with the next official version of the C++ standard (due in the next year or two). The new syntax will look exactly as you describe.
坏消息是没有相应的语法。好消息是,这将随着 C++ 标准的下一个正式版本(在未来一两年内发布)而改变。新语法将与您描述的完全一样。
回答by hlovdal
No, you cannot do that. I do not have the standard available here, so I cannot give an exact reference, but the closest thing to what you ask for is string constants, i.e.
不,你不能那样做。我这里没有可用的标准,所以我不能给出确切的参考,但最接近你要求的是字符串常量,即
function(char *);
function("mystring");
is treated by the compiler as
被编译器视为
char * some_pointer = "mystring";
function(char *);
function(some_pointer);
There is no way for other types of variables to be treated this way.
没有办法以这种方式处理其他类型的变量。
回答by Asik
Sadly, it only works with character arrays:
遗憾的是,它只适用于字符数组:
void func2(char arg[]) {
}
int main()
{
func2("hello");
return 0;
}
回答by BlindWanderer
To add to the fun, you can use templates to make it variable in length.
为了增加乐趣,您可以使用模板使其长度可变。
template<std::size_t N>
int chars(const char(&r)[N]){
std::cout << N << ": " << r << std::endl;
return 0;
}
template<std::size_t N>
int floats(const float(&r)[N]){
std::cout << N << ":";
for(size_t i = 0; i < N; i++)
std::cout << " " << r[i];
std::cout << std::endl;
return 0;
}
int main(int argc, char ** argv) {
chars("test");
floats({1.0f, 2.0f, 3.0f, 4.0f});
return 0;
}
回答by George Godik
you can write a builder class that would allow for about the same syntax
您可以编写一个允许使用大致相同语法的构建器类
// roughly
template <typename C>
class Builder {
public:
template <typename T>
Builder(const T & _data) { C.push_back(_data); }
template <typename T>
Builder& operator()(const T & _data) {
C.push_back(_data);
return *this;
}
operator const C & () const { return data; }
private:
C data;
};
this way, you can use the class as
这样,您可以将类用作
foo( const std::vector & v);
foo( const std::vector & v);
foo( Builder< std::vector >(1)(2)(3)(4) );
foo( Builder< std::vector >(1)(2)(3)(4) );