Related
This is an excercise in my textbook. I need to find the output of this code.
#include<iostream>
using namespace std;
int main()
{
int x[]={10,20,30,40,50};
int *p,**q,*t;
p=x;
t=x+1;
q=&t;
cout<<*p<<","<<**q<<","<<*t++;
return 0;
}
The output is
10,30,20
Here I dont understand the declaration of **q, and also how its value comes out to be 30. I also noticed that changing the last statement to
cout<<*p<<","<<**q<<","<<*t;
changes the output to
10,20,20
Could somebody explain what goes on behind the scenes here? Thanks a lot in advance.
Here, q is a pointer to a pointer to int, and it was set to point to t. So *q is identical to t, and **q is *t. Which means the cout expression can be rewritten as:
cout<<*p<<","<<*t<<","<<*t++;
Here you can see that t is read and modified in different parts of the expression, and the standard says that the order in which these parts are executed is not specified. So t may be modified before or after (or even while) it is read. When this kind of thing (unsequenced read and write to a variable) happens, we get undefined behavior: Anything can happen as a result. A specific compiler may give a specific result on a specific computer, but there is no guarantee that you will always get this result.
So this exercise is invalid, and there is no point in trying to figure out why you saw a specific output.
On the other hand, the second line you attempted:
cout<<*p<<","<<**q<<","<<*t;
is perfectly valid, because it doesn't modify t anywhere.
p and t are both of the type pointer to int, q is of the type pointer to (pointer to int)
The * operator makes a pointer to a reference.
So *p is of the type int&, so is *t.
*q is of the type int*& (read reference to a pointer to int)
You want to print an int value here and must therefore use the * operator a second time.
So the **q is just making a pointer to a pointer to int to a reference to int
I forgot to mention it: The process is called dereferencing pointers.
Maybe the descirption on this side will give you a better insight:
http://www.cplusplus.com/doc/tutorial/pointers/
++ operator has higher precedence than <<
When program is executed this are events:
int x[]={10,20,30,40,50};
int *p,**q,*t;
p=x;
t=x+1;
q=&t;
cout<<*p<<","<<**q<<","<<*t++; //1st change value of t to t+1,
//but return old t in place ^
//then to output stream 'p'=10, then 'q'=new 't'=old 't'+1=30,
//then old 't'=20 which is returned by sufix ++ operator
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. 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. 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) to return a pointer, in order to access with indexing. 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).
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. The program would know how many elements are in value, but it would be faster to run everything inside a for loop than not.
So why does my second block of code produce the "Warning returning temporary scope blahblahblah" warning?
UPDATE: Major XY problem here.
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. So the way to access some value in the for loop with an index would be int foo = convert(&maybeArray)[counter]; Then I would use foo several times in the for loop.
For some reason Visual Studio was throwing an error while with the second block of code. Added this to 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. Referencing convert would be more future proof I would believe.
You've tagged this as C++, so I'm assuming you are using a C++ compiler.
There's a lot going on in your question, so I'm going to simplify. You want a C++ function convert(x) that will:
if x is an array, return the address of the first element
if x is not an array, return &x.
(Generally, maybe you need to redesign this whole thing, convert seems like a pretty strange function to want).
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. 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, e.g. arrays in parameter lists foo(int is_really_a_pointer[5]) { ...}. See the comment by #MSalters for more. 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.
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; where, of course, a non-array is treated as an array of one element.
In C, there exist only pass by value. 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
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, i.e make p and p1 points to the same location.
any changes to the location pointed by p1 in function foo is reflected to *p because p and p1 is pointing to same location. But, if at any point p1 points to another location then this does not imply that p will point to that location too. p and p1 are two different pointers.
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. In this case no need to return *value, but returning do no harm.
I'm not sure if this is a proper programming question, but it's something that has always bothered me, and I wonder if I'm the only one.
When initially learning C++, I understood the concept of references, but pointers had me confused. Why, you ask? Because of how you declare a pointer.
Consider the following:
void foo(int* bar)
{
}
int main()
{
int x = 5;
int* y = NULL;
y = &x;
*y = 15;
foo(y);
}
The function foo(int*) takes an int pointer as parameter. Since I've declared y as int pointer, I can pass y to foo, but when first learning C++ I associated the * symbol with dereferencing, as such I figured a dereferenced int needed to be passed. I would try to pass *y into foo, which obviously doesn't work.
Wouldn't it have been easier to have a separate operator for declaring a pointer? (or for dereferencing). For example:
void test(int# x)
{
}
In The Development of the C Language, Dennis Ritchie explains his reasoning thusly:
The second innovation that most clearly distinguishes C from its
predecessors is this fuller type structure and especially its
expression in the syntax of declarations... given an object of any
type, it should be possible to describe a new object that gathers
several into an array, yields it from a function, or is a pointer to
it.... [This] led to a
declaration syntax for names mirroring that of the expression syntax
in which the names typically appear. Thus,
int i, *pi, **ppi; declare an integer, a pointer to an integer, a
pointer to a pointer to an integer. The syntax of these declarations
reflects the observation that i, *pi, and **ppi all yield an int type
when used in an expression.
Similarly, int f(), *f(), (*f)(); declare
a function returning an integer, a function returning a pointer to an
integer, a pointer to a function returning an integer. int *api[10],
(*pai)[10]; declare an array of pointers to integers, and a pointer to
an array of integers.
In all these cases the declaration of a
variable resembles its usage in an expression whose type is the one
named at the head of the declaration.
An accident of syntax contributed to the perceived complexity of the
language. The indirection operator, spelled * in C, is syntactically a
unary prefix operator, just as in BCPL and B. This works well in
simple expressions, but in more complex cases, parentheses are
required to direct the parsing. For example, to distinguish
indirection through the value returned by a function from calling a
function designated by a pointer, one writes *fp() and (*pf)()
respectively. The style used in expressions carries through to
declarations, so the names might be declared
int *fp(); int (*pf)();
In more ornate but still realistic cases,
things become worse: int *(*pfp)(); is a pointer to a function
returning a pointer to an integer.
There are two effects occurring.
Most important, C has a relatively rich set of ways of describing
types (compared, say, with Pascal). Declarations in languages as
expressive as C—Algol 68, for example—describe objects equally hard to
understand, simply because the objects themselves are complex. A
second effect owes to details of the syntax. Declarations in C must be
read in an `inside-out' style that many find difficult to grasp.
Sethi [Sethi 81] observed that many of the nested
declarations and expressions would become simpler if the indirection
operator had been taken as a postfix operator instead of prefix, but
by then it was too late to change.
The reason is clearer if you write it like this:
int x, *y;
That is, both x and *y are ints. Thus y is an int *.
That is a language decision that predates C++, as C++ inherited it from C. I once heard that the motivation was that the declaration and the use would be equivalent, that is, given a declaration int *p; the expression *p is of type int in the same way that with int i; the expression i is of type int.
Because the committee, and those that developed C++ in the decades before its standardisation, decided that * should retain its original three meanings:
A pointer type
The dereference operator
Multiplication
You're right to suggest that the multiple meanings of * (and, similarly, &) are confusing. I've been of the opinion for some years that it they are a significant barrier to understanding for language newcomers.
Why not choose another symbol for C++?
Backwards-compatibility is the root cause... best to re-use existing symbols in a new context than to break C programs by translating previously-not-operators into new meanings.
Why not choose another symbol for C?
It's impossible to know for sure, but there are several arguments that can be — and have been — made. Foremost is the idea that:
when [an] identifier appears in an expression of the same form as the declarator, it yields an object of the specified type. {K&R, p216}
This is also why C programmers tend to[citation needed] prefer aligning their asterisks to the right rather than to the left, i.e.:
int *ptr1; // roughly C-style
int* ptr2; // roughly C++-style
though both varieties are found in programs of both languages, varyingly.
Page 65 of Expert C Programming: Deep C Secrets includes the following: And then, there is the C philosophy that the declaration of an object should look like its use.
Page 216 of The C Programming Language, 2nd edition (aka K&R) includes: A declarator is read as an assertion that when its identifier appears in an expression of the same form as the declarator, it yields an object of the specified type.
I prefer the way van der Linden puts it.
Haha, I feel your pain, I had the exact same problem.
I thought a pointer should be declared as &int because it makes sense that a pointer is an address of something.
After a while I thought for myself, every type in C has to be read backwards, like
int * const a
is for me
a constant something, when dereferenced equals an int.
Something that has to be dereferenced, has to be a pointer.
Is this correct?
int (*(*ptr)())[];
I know this is trivial, but I was looking at an old test about these kind of constructs, and this particular combination wasn't on the test and it's really driving me crazy; I just have to make sure. Is there a clear and solid understandable rule to these kind of declarations?
(ie: pointer to... array of.. pointers to... functions that.... etc etc)
Thanks!
R
The right-left rule makes it easy.
int (*(*ptr)())[];can be interpreted as
Start from the variable name ------------------------------- ptr
Nothing to right but ) so go left to find * -------------- is a pointer
Jump out of parentheses and encounter () ----------- to a function that takes no arguments(in case of C unspecified number of arguments)
Go left, find * ------------------------------------------------ and returns a pointer
Jump put of parentheses, go right and hit [] ---------- to an array of
Go left again, find int ------------------------------------- ints.
In almost all situations where you want to return a pointer to an array the simplest thing to do is to return a pointer to the first element of the array. This pointer can be used in the same contexts as an array name an provides no more or less indirection than returning a pointer of type "pointer to array", indeed it will hold the same pointer value.
If you follow this you want a pointer to a function returning a pointer to an int. You can build this up (construction of declarations is easier than parsing).
Pointer to int:
int *A;
Function returning pointer to int:
int *fn();
pointer to function returning a pointer to int:
int *(*pfn)();
If you really want to return a pointer to a function returning a pointer to an array of int you can follow the same process.
Array of int:
int A[];
Pointer to array of int:
int (*p)[];
Function returning pointer ... :
int (*fn())[];
Pointer to fn ... :
int (*(*pfn)())[];
which is what you have.
You don't. Just split it up into two typedefs: one for pointer to int array, and one for pointer to functions. Something like:
typedef int (*IntArrayPtr_t)[];
typedef IntArrayPtr_t (*GetIntArrayFuncPtr_t)(void);
This is not only more readable, it also makes it easier to declare/define the functions that you are going to assign the variable:
IntArrayPtr_t GetColumnSums(void)
{ .... }
Of course this assumes this was a real-world situation, and not an interview question or homework. I would still argue this is a better solution for those cases, but that's only me. :)
If you feel like cheating:
typedef int(*PtrToArray)[5];
PtrToArray function();
int i = function;
Compiling that on gcc yields: invalid conversion from 'int (*(*)())[5]' to 'int'. The first bit is the type you're looking for.
Of course, once you have your PtrToArray typedef, the whole exercise becomes rather more trivial, but sometimes this comes in handy if you already have the function name and you just need to stick it somewhere. And, for whatever reason, you can't rely on template trickery to hide the gory details from you.
If your compiler supports it, you can also do this:
typedef int(*PtrToArray)[5];
PtrToArray function();
template<typename T> void print(T) {
cout << __PRETTY_FUNCTION__ << endl;
}
print(function);
Which, on my computer box, produces void function(T) [with T = int (* (*)())[5]]
Being able to read the types is pretty useful, since understanding compiler errors is often dependent on your ability to figure out what all those parenthesis mean. But making them yourself is less useful, IMO.
Here's my solution...
int** (*func)();
Functor returning an array of int*'s. It isn't as complicated as your solution.
Using cdecl you get the following
cdecl> declare a as pointer to function returning pointer to array of int;
Warning: Unsupported in C -- 'Pointer to array of unspecified dimension'
(maybe you mean "pointer to object")
int (*(*a)())[]
This question from C-faq is similar but provides 3 approaches to solve the problem.
I'm relatively new to C++ (about one year of experience, on and off). I'm curious about what led to the decision of type * name as the syntax for defining pointers. It seems to me that the syntax should be type & name as the & symbol is used everywhere else in code to refer to the variable's memory address. So, to use the traditional example of int pointers:
int a = 1;
int * b = &a;
would become
int a = 1;
int & b = &a
I'm sure there's some reason for this that I'm just not seeing, and I'd love to hear some input from C++ veterans.
Thanks,
-S
C++ adopts the C syntax. As revealed in "The Development of the C Language" (by Dennis Ritchie) C uses * for pointers in type declarations because it was decided that type syntax should follow use.
For each object of [a compound type], there was already a way to mention the underlying object: index the array, call the function, use the indirection operator [*] on the pointer. Analogical reasoning led to a declaration syntax for names mirroring that of the expression syntax in which the names typically appear. Thus,
int i, *pi, **ppi;
declare an integer, a pointer to an integer, a pointer to a pointer to an integer. The syntax of these declarations reflects the observation that i, *pi, and **ppi all yield an int type when used in an expression.
Here's a more complex example:
int *(*foo)[4][];
This declaration means an expression *(*foo)[4][0] has type int, and from that (and that [] has higher precedence than unary *) you can decode the type: foo is a pointer to an array of size 4 of array of pointers to ints.
This syntax was adopted in C++ for compatibility with C. Also, don't forget that C++ has a use for & in declarations.
int & b = a;
The above line means a reference variable refering to another variable of type int. The difference between a reference and pointer roughly is that references are initialized only, and you can not change where they point, and finally they are always dereferenced automatically.
int x = 5, y = 10;
int& r = x;
int sum = r + y; // you do not need to say '*r' automatically dereferenced.
r = y; // WRONG, 'r' can only have one thing pointing at during its life, only at its infancy ;)
I think that Dennis Ritchie answered this in The Development of the C Language:
For each object of such a composed
type, there was already a way to
mention the underlying object: index
the array, call the function, use the
indirection operator on the pointer.
Analogical reasoning led to a
declaration syntax for names mirroring
that of the expression syntax in which
the names typically appear. Thus,
int i, *pi, **ppi;
declare an integer, a pointer to an
integer, a pointer to a pointer to an
integer. The syntax of these
declarations reflects the observation
that i, *pi, and **ppi all yield an
int type when used in an expression.
Similarly,
int f(), *f(), (*f)();
declare a function returning an
integer, a function returning a
pointer to an integer, a pointer to a
function returning an integer;
int *api[10], (*pai)[10];
declare an array of pointers to
integers, and a pointer to an array of
integers. In all these cases the
declaration of a variable resembles
its usage in an expression whose type
is the one named at the head of the
declaration.
So we use type * var to declare a pointer because this allows the declaration to mirror the usage (dereferencing) of the pointer.
In this article, Ritchie also recounts that in "NB", an extended version of the "B" programming language, he used int pointer[] to declare a pointer to an int, as opposed to int array[10] to declare an array of ints.
If you are a visual thinker, it may help to imagine the asterisk as a black hole leading to the data value. Hence, it is a pointer.
The ampersand is the opposite end of the hole, think of it as an unraveled asterisk or a spaceship wobbling about in an erratic course as the pilot gets over the transition coming out of the black hole.
I remember being very confused by C++ overloading the meaning of the ampersand, to give us references. In their desperate attempt to avoid using any more characters, which was justified by the international audience using C and known issues with keyboard limitations, they added a major source of confusion.
One thing that may help in C++ is to think of references as pre-prepared dereferenced pointers. Rather than using &someVariable when you pass in an argument, you've already used the trailing ampersand when you defined someVariable. Then again, that might just confuse you further!
One of my pet hates, which I was unhappy to see promulgated in Apple's Objective-C samples, is the layout style int *someIntPointer instead of int* someIntPointer
IMHO, keeping the asterisk with the variable is an old-fashioned C approach emphasizing the mechanics of how you define the variable, over its data type.
The data type of someIntPointer is literally a pointer to an integer and the declaration should reflect that. This does lead to the requirement that you declare one variable per line, to avoid subtle bugs such as:
int* a, b; // b is a straight int, was that our intention?
int *a, *b; // old-style C declaring two pointers
int* a;
int* b; // b is another pointer to an int
Whilst people argue that the ability to declare mixed pointers and values on the same line, intentionally, is a powerful feature, I've seen it lead to subtle bugs and confusion.
Your second example is not valid C code, only C++ code. The difference is that one is a pointer, whereas the other is a reference.
On the right-hand side the '&' always means address-of. In a definition it indicates that the variable is a reference.
On the right-hand side the '*' always means value-at-address. In a definition it indicates that the variable is a pointer.
References and pointers are similar, but not the same. This article addresses the differences.
Instead of reading int* b as "b is a pointer to int", read it as int *b: "*b is an int". Then, you have & as an anti-*: *b is an int. The address of *b is &*b, or just b.
I think the answer may well be "because that's the way K&R did it."
K&R are the ones who decided what the C syntax for declaring pointers was.
It's not int & x; instead of int * x; because that's the way the language was defined by the guys who made it up -- K&R.