关于 C++(或 C)中的指针的函数作用域
Function scope regarding pointers in C++ (or C)
我正在尝试编写可移植代码,允许函数访问数组等变量,即使它只是一个值。它背后的想法是代码不会生成大小为 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(&foo)
。这应该有效,并且(我认为)它避免返回临时函数范围地址。转换的结果可以通过索引访问。在受控的 for 循环中,代码将平稳运行。程序会知道有多少元素是值,但在 for 循环中运行所有元素会比不运行所有元素更快。
那么,为什么我的第二个代码块会产生"警告返回临时范围等等"警告呢?
更新:这里的主要XY问题。
基本上,我试图将所有代码包装在一个循环中,并访问变量中的每个值,每个循环迭代一个值。系统将知道该变量中有多少个值,但代码库太大,以至于将所有内容包装在 if/else 中会很慢。因此,使用索引访问 for 循环中某些值的方法将是int foo = convert(&maybeArray)[counter];
然后我会在 for 循环中多次使用 foo。出于某种原因,Visual Studio在使用第二个代码块时抛出错误。将此添加到 OP 中。
另一种解决方案是使用重载运算符制作 2 个函数,这些运算符基本上可以执行整个代码,而无需转换每个变量,但代码库非常大,这需要尽可能可移植。我相信,参考convert
将更能证明未来。
您已经将其标记为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
以清楚起见。
最后,也许与其将数组转换为指针,不如要求一个将非数组转换为对单元素数组的引用的函数?
更新 下面是一个更完整的示例,展示了如何使用convert
和convert_end
来查找数组的开头和结尾,以迭代数组中的所有元素;当然,非数组被视为一个元素的数组。
在 C 中,仅存在按值传递。将指针传递给函数时,其地址将复制到函数参数。这只是意味着,如果p
是调用函数的指针,则函数调用
int x = 5;
int *p = &x;
int a = foo(p);
用于函数定义
int foo(int *p1)
{
return *p1*2;
}
意味着:
- 将地址
p
指向参数p1
,即将p
和p1
指向同一位置。 - 函数 foo 中
p1
所指向的位置的任何更改都会反映到*p
,因为p
和p1
指向同一位置。但是,如果在任何时候p1
指向另一个位置,这并不意味着p
也会指向该位置。p
和p1
是两个不同的指针。
当您将指针传递给指针时,就像在第二个块的最后一个片段中一样,
int * convert(int ** value)
{return *value;}
如果在将参数传递给它后*value
更改为指向不同的位置,则传递其地址的指针也将使用此位置进行更新。在这种情况下,无需返回*value
,但返回不会造成伤害。
- 如何正确编写指针函数声明?
- C++常规指针函数或模板
- 如何重新定义 C++ 指针函数?
- C++ 指向其他类函数的指针函数
- 指针到指针函数参数
- 将指向成员的指针函数传递到模板中
- C++ 在 none 常量指针函数中返回一个常量指针
- 如何使用指针函数编写/读取数组
- 是C 中的函数指针函数对象
- 如何从另一个类调用指向成员的指针函数
- 如何声明采用指向成员的指针函数的函数
- 如何构造一个以可变参数指针函数作为成员的类?
- c 通过值或指针函数语法
- 将typedef方法作为指针函数传递
- 从 Main 中的双指针函数打印出指针数组
- strcpy 对指针函数的引用
- 这是否仍然声明一种指针函数的别名?
- 将指向成员的指针函数与 std::shared_ptr 结合使用
- 'Incomplete type' 为标准::函数声明指向成员的指针函数模板参数时出错
- 从注入进程的 DLL 调用函数并更改指针函数的地址