简体   繁体   English

关于C ++(或C)中指针的函数范围

[英]Function scope regarding pointers in C++ (or C)

I am attempting to write portable code that allows the function to access a variable like an array, even if it is just a single value. 我试图编写可移植代码,允许函数访问类似数组的变量,即使它只是一个值。 The idea behind it is that the code will not make an array of size 1, but I need to be able to loop over all the values in the array if it is an array. 它背后的想法是代码不会生成大小为1的数组,但是如果它是一个数组,我需要能够遍历数组中的所有值。 Since I can't use sizeof(foo) to determine whether the memory is larger than a single instance sizeof(foo)/sizeof(int) might work, but it is too cumbersome to include in the main code. 由于我无法使用sizeof(foo)来确定内存是否大于单个实例sizeof(foo)/sizeof(int)可能有效,但包含在主代码中太麻烦了。 Macros wouldn't help because if I used a ternary operator like I'd expect #define ARRAY_OR_NOT(foo, type) (sizeof(foo)/sizeof(type) > 1) ? (foo) : (&foo) 宏不会有帮助,因为如果我使用三元运算符,我希望#define ARRAY_OR_NOT(foo, type) (sizeof(foo)/sizeof(type) > 1) ? (foo) : (&foo) #define ARRAY_OR_NOT(foo, type) (sizeof(foo)/sizeof(type) > 1) ? (foo) : (&foo) to return a pointer, in order to access with indexing. #define ARRAY_OR_NOT(foo, type) (sizeof(foo)/sizeof(type) > 1) ? (foo) : (&foo)返回一个指针,以便通过索引进行访问。 This problem is the compiler doesn't like the mixing of types between pointers and non-pointers. 这个问题是编译器不喜欢指针和非指针之间的类型混合。

So my second attempt was function overloading. 所以我的第二次尝试是函数重载。

int * convert(int value)
    {return &value;}
int * convert(int * value)
    {return value;}

I know that this wouldn't work, because the first function would return the address of the temporary variable copy in that function scope. 我知道这不起作用,因为第一个函数将返回该函数范围中临时变量副本的地址。 So my third attempt was 所以我的第三次尝试是

int * convert(int * value)
    {return value;}
int * convert(int ** value)
    {return *value;}

Every time I would call convert, pass the address of the value: convert(&foo) . 每次我调用convert时,都要传递值的地址: convert(&foo) This should work, and (I think) it avoids returning a temporary function scope address. 这应该工作,并且(我认为)它避免返回临时函数范围地址。 The result of convert would be accessible with indexing. 转换的结果可以通过索引来访问。 In a controlled for loop, the code would run smoothly. 在受控的for循环中,代码将平稳运行。 The program would know how many elements are in value, but it would be faster to run everything inside a for loop than not. 程序会知道有多少元素是有价值的,但是在for循环中运行所有内容比没有更快。

So why does my second block of code produce the "Warning returning temporary scope blahblahblah" warning? 那么为什么我的第二个代码块会产生“警告返回临时范围blahblahblah”警告?

UPDATE: Major XY problem here. 更新:这里的主要XY问题。

Basically I'm trying to wrap all my code in a loop and access each value in a variable, one value per loop iteration. 基本上我正在尝试将所有代码包装在一个循环中并访问变量中的每个值,每个循环迭代一个值。 The system would know how many values are in that variable, but the code base is so large that wrapping everything in an if/else would be slow. 系统会知道该变量中有多少个值,但代码库太大以至于将if / else中的所有内容包装起来都会很慢。 So the way to access some value in the for loop with an index would be int foo = convert(&maybeArray)[counter]; 因此,使用索引访问for循环中某些值的方法是int foo = convert(&maybeArray)[counter]; Then I would use foo several times in the for loop. 然后我会在for循环中多次使用foo。 For some reason Visual Studio was throwing an error while with the second block of code. 出于某种原因,Visual Studio在使用第二个代码块时抛出错误。 Added this to OP. 将此添加到OP。

Another solution would be to make 2 functions with overloaded operators that would basically execute the entire code, without converting each variable, but the code base is very large, and this needs to be as portable as possible. 另一种解决方案是使用重载运算符创建2个函数,这些函数基本上可以执行整个代码,而不需要转换每个变量,但代码库非常大,并且这需要尽可能的可移植。 Referencing convert would be more future proof I would believe. 引用convert将是我相信的更多未来证明。

You've tagged this as C++ , so I'm assuming you are using a C++ compiler. 您已将其标记为C++ ,因此我假设您使用的是C ++编译器。

There's a lot going on in your question, so I'm going to simplify. 你的问题有很多,所以我要简化。 You want a C++ function convert(x) that will: 你想要一个C ++函数convert(x) ,它将:

  1. if x is an array, return the address of the first element 如果x是数组,则返回第一个元素的地址
  2. if x is not an array, return &x . 如果x不是数组,则返回&x

(Generally, maybe you need to redesign this whole thing, convert seems like a pretty strange function to want). (一般来说,也许你需要重新设计这一切, 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;
}

And, in C++, I would never use sizeof with things that I think are arrays. 并且,在C ++中,我永远不会将sizeof用于 我认为 是数组的东西。 This template technique is a safer way to count the number of elements in an array. 此模板技术是计算数组中元素数量的更安全的方法。

Also, do you expect to have arrays of pointers, and to want to treat a single pointer as a single-element-array of pointers? 另外,你期望有指针数组,并希望将单个指针视为指针的单元素数组吗? If so, then tread carefully. 如果是这样,那就小心翼翼。 Something that looks like an array, might actually be a pointer, eg arrays in parameter lists foo(int is_really_a_pointer[5]) { ...} . 看起来像数组的东西实际上可能是指针,例如参数列表中的数组foo(int is_really_a_pointer[5]) { ...} See the comment by @MSalters for more. 有关更多信息,请参阅@MSalters的评论。 Might be good to use his assert to catch any surprises. 可能善于使用他的断言来捕获任何惊喜。 If you're just using int , then don't use the typename T in my templates, just force it to be int for clarity. 如果您只是使用int ,那么不要在我的模板中使用typename T ,只是为了清楚起见强制它为int

Finally, maybe instead of turning arrays into pointers, you should ask for a function that turns a non-array into a reference to a single-element array? 最后,也许不应该将数组转换为指针,你应该要求一个函数将非数组转换为对单元素数组的引用?

Update Here is a more complete example showing how to use convert and convert_end to find the beginning and end of an array to iterate over all the elements in an array; 更新这是一个更完整的示例,显示如何使用convertconvert_end查找数组的开头和结尾以迭代数组中的所有元素; where, of course, a non-array is treated as an array of one element. 当然,非数组被视为一个元素的数组。

In C, there exist only pass by value. 在C中,只存在按值传递。 When you pass a pointer to a function then its address is copied to the function parameter. 将指针传递给函数时,其地址将复制到函数参数中。 This simply means that if p is a pointer in calling function then a function call 这只是意味着如果p是调用函数中的指针,那么函数调用

int x = 5;
int *p = &x;
int a = foo(p);   

for function definition 用于功能定义

int foo(int *p1)
{
    return *p1*2;
}  

is implies that: 意味着:

  • copy the address p points to parameter p1 , ie make p and p1 points to the same location. 将地址p指向参数p1 ,即使pp1指向同一位置。
  • any changes to the location pointed by p1 in function foo is reflected to *p because p and p1 is pointing to same location. 函数foo中p1指向的位置的任何更改都会反映到*p因为pp1指向相同的位置。 But, if at any point p1 points to another location then this does not imply that p will point to that location too. 但是,如果在任何时候p1指向另一个位置,那么这并不意味着p也将指向该位置。 p and p1 are two different pointers. pp1是两个不同的指针。

When you you pass a pointer to pointer, as in your last snippet of second block, 当您将指针传递给指针时,就像在第二个块的最后一个片段中一样,

int * convert(int ** value)
{return *value;}  

if *value changes to points to different location after argument is passed to it, then that pointer whose address is passed will also be updated with this location. 如果*value在参数传递给它后更改为指向不同位置的点,那么传递地址的指针也将使用此位置进行更新。 In this case no need to return *value , but returning do no harm. 在这种情况下,不需要返回*value ,但返回不会造成伤害。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM