我正在尝试编写可移植代码,允许函数像数组一样访问变量,即使它只是一个值。它背后的想法是代码不会生成大小为1的数组,但是如果它是一个数组,我需要能够遍历数组中的所有值。由于我不能使用sizeof(foo)
来确定内存是否大于单个实例sizeof(foo)/sizeof(int)
可能有效,但包含在主代码中太麻烦了。宏不会有帮助,因为如果我使用像我这样的三元运算符,期望#define ARRAY_OR_NOT(foo, type) (sizeof(foo)/sizeof(type) > 1) ? (foo) : (&foo)
返回一个指针,以便通过索引进行访问。这个问题是编译器不喜欢在指针和非指针之间混合类型。
所以我的第二次尝试是函数重载。
int * convert(int value)
{return &value;}
int * convert(int * value)
{return value;}
我知道这不会起作用,因为第一个函数会在该函数范围内返回临时变量副本的地址。所以我的第三次尝试是
int * convert(int * value)
{return value;}
int * convert(int ** value)
{return *value;}
每次我调用convert时,都要传递值convert(&foo)
的地址。
这应该工作,并且(我认为)它避免返回临时函数范围
地址。转换的结果可以通过索引来访问。在受控的for循环中,代码将平稳运行。程序会知道有多少元素有价值,但是在for循环中运行所有内容会比没有更快。
那么为什么我的第二个代码块产生"警告返回临时范围blahblahblah"警告?
更新:这里的主要XY问题。
基本上我试图将所有代码包装在一个循环中并访问变量中的每个值,每个循环迭代一个值。系统会知道该变量中有多少个值,但代码库太大以至于将if / else中的所有内容包装起来都会很慢。因此,使用索引访问for循环中某些值的方法是int foo = convert(&maybeArray)[counter];
然后我会在for循环中多次使用foo。
出于某种原因,Visual Studio在使用第二个代码块时抛出错误。将此添加到OP。
另一种解决方案是使用重载运算符创建2个函数,这些函数基本上可以执行整个代码,而不需要转换每个变量,但代码库非常大,并且需要尽可能的可移植性。引用convert
将是我相信的未来证据。
答案 0 :(得分:2)
您已将此标记为C++
,因此我假设您使用的是C ++编译器。
你的问题还有很多,所以我要简化。你想要一个C ++函数convert(x)
:
- 如果
x
是数组,则返回第一个元素的地址- 如果
醇>x
不是数组,请返回&x
。
(一般来说,也许你需要重新设计这一切,convert
似乎是一个非常奇怪的功能。
template<typename T, size_t N>
auto convert( T (&t) [N] ) -> T* {
return t; // just let pointer decay work for us here
}
template<typename T>
auto convert( T &t) -> T* {
return &t;
}
而且,在C ++中,我绝不会将sizeof
用于我认为是数组的东西。这种模板技术是计算数组中元素数量的更安全的方法。
另外,您是否希望拥有指针数组,并希望将单个指针视为指针的单元素数组?如果是这样,那就小心翼翼。看起来像数组的东西实际上可能是指针,例如参数列表foo(int is_really_a_pointer[5]) { ...}
中的数组。有关更多信息,请参阅@MSalters的评论。可能善于使用他的断言来捕获任何惊喜。如果您只是使用int
,那么请不要在我的模板中使用typename T
,为了清楚起见,请强制它int
。
最后,也许不是将数组转换为指针,而应该要求一个函数将非数组转换为对单元素数组的引用?
更新 以下是more complete example,其中显示了如何使用convert
和convert_end
查找数组的开头和结尾迭代数组中的所有元素;当然,非数组被视为一个元素的数组。
答案 1 :(得分:1)
在C中,只存在按值传递。将指针传递给函数时,其地址将复制到函数参数中。这只是意味着如果p
是调用函数中的指针,那么函数调用
int x = 5;
int *p = &x;
int a = foo(p);
用于功能定义
int foo(int *p1)
{
return *p1*2;
}
意味着:
p
点复制到参数p1
,即将p
和p1
指向同一位置。 p1
指向的位置的任何更改都会反映到*p
,因为p
和p1
指向同一位置。但是,如果在任何时候p1
指向另一个位置,那么这并不意味着p
也将指向该位置。 p
和p1
是两个不同的指针。 当您将指针传递给指针时,就像在第二个块的最后一个片段中一样,
int * convert(int ** value)
{return *value;}
如果*value
在传递参数后更改为指向不同位置的点,则传递地址的指针也将使用此位置进行更新。在这种情况下,无需返回*value
,但返回不会造成伤害。