What is the unary-& doing here?
int * a = 1990;
int result = &5[a];
If you were to print result you would get the value 2010.
You have to compile it with -fpermissive or it will stop due to errors.
In C, x [y] and y [x] are identical. So &5[a] is the same as &a[5].
&5[a] is the same as &a[5] and the same as a + 5. In your case it's undefined behavior because a points to nowhere.
C11 standard chapter 6.5.6 Additive operators/8 (the same in C++):
If both the pointer
operand and the result point to elements of the same array object, or one past the last
element of the array object, the evaluation shall not produce an overflow; otherwise, the
behavior is undefined.
"...unary & on numeric literal"?
Postfix operators in C always have higher priority than prefix ones. In case of &5[a], the [] has higher priority than the &. Which means that in &5[a] the unary & is not applied to "numeric literal" as you seem to incorrectly believe. It is applied to the entire 5[a] subexpression. I.e. &5[a] is equivalent to &(5[a]).
As for what 5[a] means - this is a beaten-to-death FAQ. Look it up.
And no, you don't have "to compile it with -fpermissive" (my compiler tells me it doesn't even know what -fpermissive is). You have to figure out that this
int * a = 1990;
is not legal code in either C or C++. If anything, it requires an explicit cast
int * a = (int *) 1990;
not some obscure switch of some specific compiler you happened to be using at the moment. The same applies to another illegal initialization in int result = &5[a].
Finally, even if we overlook the illegal code and the undefined behavior triggered by that 5[a], the behavior of this code will still be highly implementation-dependent. I.e. the answer is no, in general case you will not get 2010 in result.
You cannot apply the unary & operator to an integer literal, because a literal is not an lvalue.
Due to operator precedence, your code doesn't do that. Since the indexing operator [] binds more tightly than unary &, &5[a] is equivalent to &(5[a]).
Here's a program similar to yours, except that it's valid code, not requiring -fpermissive to compile:
#include <stdio.h>
int main(void) {
int arr[6];
int *ptr1 = arr;
int *ptr2 = &5[ptr1];
printf("%p %p\n", ptr1, ptr2);
}
As explained in this question and my answer, the indexing operator is commutative (because it's defined in terms of addition, and addition is commutative), so 5[a] is equivalent to a[5]. So the expression &5[ptr1] computes the address of element 5 of arr.
In your program:
int * a = 1990;
int result = &5[a];
the initialization of a is invalid because a is of type int* and 1990 is of type int, and there is no implicit conversion from int to int*. Likewise, the initialization of result is invalid because &5[a] is of type int*. Apparently -fpermissive causes the compiler to violate the rules of the language and permit these invalid implicit conversions.
At least in the version of gcc I'm using, the -fpermissive option is valid only for C++ and Objective-C, not for C. In C, gcc permits such implicit conversions (with a warning) anyway. I strongly recommend not using this option. (Your question is tagged both C and C++. Keep in mind that C and C++ are two distinct, though closely related, languages. They happen to behave similarly in this case, but it's usually best to pick one language or the other.)
Related
int func(int n)
{return n;}
int main()
{ cout << func[4] ;
cout << func[4,3,5] ;}
what do these actually mean? I guess it is about accessing func+4 and func is allocated space on calling func[4].
But, func[4,3,5] is just absurd.
The reason this code compiles and func[4] is not a syntax error is:
1.Function types can implicitly convert to pointers of the same type.
So, if we have code like this:
int f(int);
using func_t = int(*)(int);
void g(func_t);
we can write
g(f)
and aren't forced to write g(&f). The &, taking us from type int(int) to int(*)(int) happens implicitly.
2.In C (and necessarily in C++ for compatibility) pointers are connected to arrays, and when p is a pointer p[x] is the same as *(p + x). So func[4] is the same as *(func + 4).
3.*(p+x) has the type of a function int(int), but again can implicitly decay to a pointer type whenever necessary. So *(func + 4) can implicitly just be (func + 4).
4.Pointers of any type are streamable to std::cout.
Note, that just because it isn't a syntax error doesn't mean it is valid. Of course it is undefined behavior, and as the compiler warning emitted by gcc and clang indicates, pointer arithmetic with a function pointer is generally wrong, because you cannot make an array of functions. The implementation places functions however it likes. (You can make an array of function pointers but that is something else entirely.)
Edit: I should correct myself -- this answer is not entirely correct. func[4] is not valid, because the pointer is not a pointer to an object type. #holyblackcat answer is correct, see his answer for reference in the standard.
This code should be ill-formed, and gcc only compiles it without an error because they are using a nonstandard extension by default. Clang and msvc correctly reject this code.
I'm surprised no answer mentions it, but:
The code in the question is simply not valid C++.
It's rejected by Clang and MSVC with no flags. GCC rejects it with -pedantic-errors.
a[b] (in absence of operator overloading) is defined as *(a + b), and the builtin operator + requires the pointer operand to be a pointer to an object type (which functions pointers are not).
[expr.add]/1
...either both operands shall have arithmetic or unscoped enumeration type, or one operand shall be a pointer to a completely-defined object type and the other shall have integral or unscoped enumeration type.
(Emphasis mine.)
GCC compiles the code because an extension allowing arithmetic on function pointer is enabled by default.
Due to function-to-pointer decay, func[4] is treated as &(&func)[4], which effectively means &func + 4, which (as the link explains) simply adds 4 to the numerical value of the pointer. Calling resulting pointer will most likely cause a crash or unpredicatble results.
std::cout doesn't have an overload of << suitable for printing function pointers, and the best suitable overload the compiler is able to find is the one for printing bools. The pointer gets converted to bool, and since it's non-null, it becomes true, which is then printed as 1.
Lastly, func[4,3,5] has the same effect as func[5], since in this context , is treated as an operator, and x , y is equal to y.
Since it has not been mentioned yet: func[3, 4, 5] is identical to func[5] - the commas in there are the builtin comma operator which evaluates the left hand side expression, discards it and then evaluates the right hand side expression. There is no function call happening here and the commas in the code are not delimiting function parameters.
Yes,It is about accessing the func+4 which is not already defined leading to a garbage value.So the compiler will indicate you with the following warning message.
hereProgram: In function 'int main()':
Program:7: warning: pointer to a function used in arithmetic
In what version(s) of the C++ standards (if any) is the following well-defined?
void foo(void) {
char *nullPtr = NULL;
&*nullPtr;
}
Note that I am specifically asking about &*nullPtr here. I am aware that simply *nullPtr is undefined - but this is a separate question and hence the currently-linked "duplicate" is not a duplicate.
Note that I am not assigning the result to anything - the second line is a simple statement.
This should be a question with an obvious answer, but (as seemingly happens way too often on such questions) I have heard just as many people say the answer is "obviously undefined" as "obviously defined".
On a rather related note, what about the following? Should foo produce a read of c?
extern volatile char c;
void bar(void) {
volatile char *nonnullptr = &c;
&*nonnullptr;
}
(C version of the same question: Is &*NULL well-defined in C?)
This is four questions in one.
&*nullPtr is well-defined in C since C99, which says of the unary & operator:
If the operand is the result of a unary * operator, neither that
operator nor the & operator is evaluated and the result is as if both
were omitted, [...]
See WG14 N721 and DR076.
&*nullPtr is formally undefined in all revisions of C++ (by omission: unary & is specified to produce a pointer to "the designated object", and unary * is specified to produce "an lvalue referring to the object [...] to which the expression points"; a null pointer value points to no object), although the direction of core issue 232 is to make this well-defined.
&*nonnullptr produces no volatile read of *nonnullptr. Unary & expects an lvalue operand; no lvalue conversion (for C) or lvalue-to-rvalue conversion (for C++) is performed for *nonnullptr.
test.(c/cpp)
#include <stdio.h>
int main(int argc, char** argv)
{
int a = 0, b = 0;
printf("a = %d, b = %d\n", a, b);
b = (++a)--;
printf("a = %d, b = %d\n", a, b);
return 0;
}
If I save the above as a .cpp file, it compiles and outputs this upon execution:
a = 0, b = 0
a = 0, b = 1
However, if I save it as a .c file, I get the following error:
test.c:7:12: error: lvalue required as decrement operator.
Shouldn't the (++a) operation be resolved before the (newValue)-- operation? Does anyone have any insight on this?
In C the result of the prefix and postfix increment/decrement operators is not an lvalue.
In C++ the result of the postfix increment/decrement operator is also not an lvalue but the result of the prefix increment/decrement operator is an lvalue.
Now doing something like (++a)-- in C++ is undefined behavior because you are modifying an object value twice between two sequence points.
EDIT: following up on #bames53 comment. It is undefined behavior in C++98/C++03 but the changes in C++11 on the idea of sequence points now makes this expression defined.
In C and C++, there are lvalue expressions which may be used on the left-hand side of the = operator and rvalue expressions which may not. C++ allows more things to be lvalues because it supports reference semantics.
++ a = 3; /* makes sense in C++ but not in C. */
The increment and decrement operators are similar to assignment, since they modify their argument.
In C++03, (++a)-- would cause undefined behavior because two operations which are not sequenced with respect to each other are modifying the same variable. (Even though one is "pre" and one is "post", they are unsequenced because there is no ,, &&, ?, or such.)
In C++11, the expression now does what you would expect. But C11 does not change any such rules, it's a syntax error.
For anybody who might want the precise details of the differences as they're stated in the standards, C99, §6.5.3/2 says:
The value of the operand of the prefix ++ operator is incremented. The result is the new
value of the operand after incrementation.
By contrast, C++11, §5.3.2/1 says:
The result is the updated operand; it is an lvalue, and it is a bit-field if
the operand is a bit-field.
[emphasis added, in both cases]
Also note that although (++a)-- gives undefined behavior (at least in C++03) when a is an int, if a is some user-defined type, so you're using your own overloads of ++ and --, the behavior will be defined -- in such a case, you're getting the equivalent of:
a.operator++().operator--(0);
Since each operator results in a function call (which can't overlap) you actually do have sequence points to force defined behavior (note that I'm not recommending its use, only noting that the behavior is actually defined in this case).
§5.2.7 Increment and decrement:
The value of a postfix ++ expression is the value of its operand. [ ... ] The operand shall be a modifiable lvalue.
The error you get in your C compilation helps to suggest that this is only a feature present in C++.
We all know that dereferencing an null pointer or a pointer to unallocated memory invokes undefined behaviour.
But what is the rule when used within an expression passed to sizeof?
For example:
int *ptr = 0;
int size = sizeof(*ptr);
Is this also undefined?
In most cases, you will find that sizeof(*x) does not actually evaluate *x at all. And, since it's the evaluation (de-referencing) of a pointer that invokes undefined behaviour, you'll find it's mostly okay. The C11 standard has this to say in 6.5.3.4. The sizeof operator /2 (my emphasis in all these quotes):
The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.
This is identical wording to the same section in C99. C89 had slightly different wording because, of course, there were no VLAs at that point. From 3.3.3.4. The sizeof operator:
The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand, which is not itself evaluated. The result is an integer constant.
So, in C, for all non-VLAs, no dereferencing takes place and the statement is well defined. If the type of *x is a VLA, that's considered an execution-phase sizeof, something that needs to be worked out while the code is running - all others can be calculated at compile time. If x itself is the VLA, it's the same as the other cases, no evaluation takes place when using *x as an argument to sizeof().
C++ has (as expected, since it's a different language) slightly different rules, as shown in the various iterations of the standard:
First, C++03 5.3.3. Sizeof /1:
The sizeof operator yields the number of bytes in the object representation of its operand. The operand is either an expression, which is not evaluated, or a parenthesized type-id.
In, C++11 5.3.3. Sizeof /1, you'll find slightly different wording but the same effect:
The sizeof operator yields the number of bytes in the object representation of its operand. The operand is either an expression, which is an unevaluated operand (Clause 5), or a parenthesized type-id.
C++11 5. Expressions /7 (the above mentioned clause 5) defines the term "unevaluated operand" as perhaps one of the most useless, redundant phrases I've read for a while, but I don't know what was going through the mind of the ISO people when they wrote it:
In some contexts ([some references to sections detailing those contexts - pax]), unevaluated operands appear. An unevaluated operand is not evaluated.
C++14/17 have the same wording as C++11 but not necessarily in the same sections, as stuff was added before the relevant parts. They're in 5.3.3. Sizeof /1 and 5. Expressions /8 for C++14 and 8.3.3. Sizeof /1 and 8. Expressions /8 for C++17.
So, in C++, evaluation of *x in sizeof(*x) never takes place, so it's well defined, provided you follow all the other rules like providing a complete type, for example. But, the bottom line is that no dereferencing is done, which means it does not cause a problem.
You can actually see this non-evaluation in the following program:
#include <iostream>
#include <cmath>
int main() {
int x = 42;
std::cout << x << '\n';
std::cout << sizeof(x = 6) << '\n';
std::cout << sizeof(x++) << '\n';
std::cout << sizeof(x = 15 * x * x + 7 * x - 12) << '\n';
std::cout << sizeof(x += sqrt(4.0)) << '\n';
std::cout << x << '\n';
}
You might think that the final line would output something vastly different to 42 (774, based on my rough calculations) because x has been changed quite a bit. But that is not actually the case since it's only the type of the expression in sizeof that matters here, and the type boils down to whatever type x is.
What you do see (other than the possibility of different pointer sizes on lines other than the first and last) is:
42
4
4
4
4
42
No. sizeof is an operator, and works on types, not the actual value (which is not evaluated).
To remind you that it's an operator, I suggest you get in the habit of omitting the brackets where practical.
int* ptr = 0;
size_t size = sizeof *ptr;
size = sizeof (int); /* brackets still required when naming a type */
The answer may well be different for C, where sizeof is not necessarily a compile-time construct, but in C++ the expression provided to sizeof is never evaluated. As such, there is never a possibility for undefined behavior to exhibit itself. By similar logic, you can also "call" functions that are never defined [because the function is never actually called, no definition is necessary], a fact that is frequently used in SFINAE rules.
sizeof and decltype do not evaluate their operands, computing types only.
sizeof(*ptr) is the same as sizeof(int) in this case.
Since sizeof does not evaluate its operand (except in the case of variable length arrays if you're using C99 or later), in the expression sizeof (*ptr), ptr is not evaluated, therefore it is not dereferenced. The sizeof operator only needs to determine the type of the expression *ptr to get the appropriate size.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Take the address of a one-past-the-end array element via subscript: legal by the C++ Standard or not?
int array[10];
int* a = array + 10; // well-defined
int* b = &array[10]; // not sure...
Is the last line valid or not?
Yes, you can take the address one beyond the end of an array, but you can't dereference it. For your array of 10 items, array+10 would work. It's been argued a few times (by the committee, among others) whether &array[10] really causes undefined behavior or not (and if it does, whether it really should). The bottom line with it is that at least according to the current standards (both C and C++) it officially causes undefined behavior, but if there's a single compiler for which it actually doesn't work, nobody in any of the arguments has been able to find or cite it.
Edit: For once my memory was half correct -- this was (part of) an official Defect Report to the committee, and at least some committee members (e.g., Tom Plum) thought the wording had been changed so it would not cause undefined behavior. OTOH, the DR dates from 2000, and the status is still "Drafting", so it's open to question whether it's really fixed, or ever likely to be (I haven't looked through N3090/3092 to figure out).
In C99, however, it's clearly not undefined behavior.
As other answers have indicated, the expression array[10] is equivalent to *(array + 10), which would appear to result in an undefined dereferencing of the element just past the end of the array. however, the expression &array[10] is equivalent to &*(array + 10), and the C99 standard makes clear (6.5.3.2 Address and indirection operators):
The unary & operator returns the address of its operand. If the operand has type ‘‘type’’, the result has type ‘‘pointer to type’’. If the operand is the result of a unary * operator, neither that operator nor the & operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue. Similarly, if the operand is the result of a [] operator, neither the & operator nor the unary * that is implied by the [] is evaluated and the result is as if the & operator were removed and the [] operator were changed to a + operator.
So, there's nothing undefined about &array[10] - there is no dereference operation that takes place.
No. It's undefined. array[10] amounts to *(array + 10). In other words, you've dereferenced an invalid pointer.
array[10] is equivalent to *(array + 10) (and also equivalent to 10[array]), so &array[10] acts like removing the * from *(array+10). Any decent compiler should emit the same code (and the same warning).
This is actually a fairly simple thing to answer.
All you are doing is pointer math, there is nothing invalid about it. If you try to USE the resulting pointers in some way then depends on whether or not your process has access to the memory pointed to by that pointer, and if so what are the permissions on it?
foo.cc:
#include <iostream>
using namespace std;
int main() {
int array[10];
int *a = array + 10;
int *b = &array[10];
int *c = &array[3000];
cerr << "Pointers values are: " << a << " " << b << " " << c << endl;
return 0;
}
To Compile:
g++ -Werror -Wall foo.cc -o foo
should yield NO warnings because the int *b = &array[10] is valid
Actually so is the subsequent line added by me to just point something out about pointer math.
not only will foo compile, it will run without a hitch:
./foo
Pointers are: 0x7fff1d356e68 0x7fff1d356e68 0x7fff1d359d20
Basically array syntax foo[idx] is short cut and clean representation of pointer math.
In case there is some confusion regarding c99, the standard DOES NOT affect this math in anyway and well defined.
The same thing in C99:
#include <stdio.h>
int main() {
int array[10];
int *a = array + 10;
int *b = &array[10];
int *c = &array[3000];
fprintf(stderr, "Pointers are: %p, %p, %p\n" , a , b , c );
return 0;
}
Then:
gcc -std=c99 -Wall -Werror -o foo foo.c
./foo
Outputs:
Pointers are: 0x7fff2c7d22c8, 0x7fff2c7d22c8, 0x7fff2c7d5180