What is the use of unary plus operator in pointer initialization? - c

I know that C & C++ both are different languages, today I make a little typo in the following program but the program compiles fine on various C++ compilers (g++,clang,MSVC++)
Consider following program:
int main()
{
int s[]={3,6,9,12,18};
int* p=+s; // Observe this strange looking initialization due to use of unary + operator
}
The above program compiles fine in C++ (See live demo here) but not in C (See live demo here.) My compiler ( gcc 4.8.1 ) gives me following error when I compile it as a C program.
[Error] wrong type argument to unary plus
What purpose the unary plus operator serves here? What it does exactly here? Why it is not allowed in C?

The section 6.5.3.3 of C99 states:
1) The operand of the unary + or - operator shall have arithmetic type;
......
2) The result of the unary + operator is the value of its (promoted)
operand. The integer promotions are performed on the operand, and the
result has the promoted type.
Pointers or arrays are not an arithmetic type.

What purpose the unary plus operator serves here?
In C++, the behavior is laid out in section 5.3.1:
[2] The result of each of the following unary operators is a prvalue.
[7] The operand of the unary + operator shall have arithmetic, unscoped enumeration, or pointer type and the result is the value of the argument.
Sometimes people use this operator to "force" decay, i.e. in this case an array to pointer. But it is rather redundant since the conversion happens automatically.
What it does exactly here? Why it is not allowed in C?
Because the special meaning simply does not exist.

s will be treated as a pointer not as an array when + operator is called.
For C, it seems that this concept was not introduced yet.

I have only ever seen this used in situations where the unary + operator has been overloaded in an OOP language like C++. It hasn't got a purpose in C apart from possible causing errors like this where a pointer was accidentally passed to a macro or a function that does not expect one.
Either way it's a nasty way to write code, if there was a good reason for it then it should be accompanied by an explanatory comment from the original author.

Related

If pointer ptr contains an arbitrary value (as per our choice), then is *ptr actually performed while calculating &*ptr?

I have heard many people saying that in C * and & actually nullify the effects of each other, in situations wherever they are valid.
Suppose just for illustration I define and initialize a pointer as follows:
int *ptr=2000;
Clearly the value which I assigned to ptr is arbitrary and trying to deference it might possibly cause segmentation fault. I do not exactly remember the entire code, but I once read a data structure book where the author was showing some calculations on structural padding. I guess there was statements which roughly meant something like this:
int *newptr=&*ptr;
Like those many people I felt that & and * cancelled each other and we have newptr assigned the value of ptr namely 2000 in the above example.
The statement that & and * cancel each other is not always true. Take the case of an integer variable. And if we apply somethings as:
int x=10;
int y=&*x;
The compiler quite naturally puts forth an error saying invalid type argument of unary ‘*’ (have ‘int’). This is quite clear from the way C tries to parse the expression &*x. Which is like (&(*x))
Now coming back to the actual question, C should parse the expression &*ptr as (&(*ptr)). So what I feel is that first *ptr should be calculated and then address of it should be taken. But this brings up a possibility of segmentation fault while trying to do *ptr first, given that ptr contains some garbage.
I tried quite many times the same thing, by randomly assigning a value to ptr by a random number generator and then applying &*ptr. But luckily none of the times there was any segmentation fault.
May be I was very lucky. But given the situation I feel that it is quite unlikely that I am getting lucky each and everytime and possibly C compiler is doing something smart contrary to what I have thought. Probably on just seeing &* applied to a pointer, it just uses the raw value of the pointer instead of just going into the headache of first (*ptr) and then taking & of the result.
But the thing is that, I am unable to figure out as to what is the situation actually. Please can anyone help me out?
The pointer is not actually dereferenced, so there is no UB.
C11 — 6.5.3.2 Address and indirection operators
3 — ... 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.
Now, you might be wondering if the pointer being valid is a part of the "constraints". Apparently not, because right above that there's following section:
Constraints
1 — The operand of the unary & operator shall be either a function designator, the result of a [] or unary * operator, or an lvalue that designates an object that is not a bit-field and is not declared with the register storage-class specifier.
2 — The operand of the unary * operator shall have pointer type.

Is &*NULL well-defined in C?

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 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++?)
While attempts to dereference a null pointer cause undefined behavior, so *nullPtr is illegal, &*nullPtr is perfectly well-defined. According to footnote 102 in the C11 Draft Standard:
Thus, &*E is equivalent to E (even if E is a null pointer),....
This is a result of the fact that, for the unary & operator (§6.5.3.2 ¶3):
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,....
The C99 Standard has the same language, but this does not appear in the C90 Standard, and my reading of that standard is that &*nullPtr would indeed cause undefined behavior in pre-C99 implementations.
From the C90 Standard (§6.3.2.3):
The result of the unary & (address-of) operator is a pointer to the object or function designated by its operand....
and:
The unary * operator denotes indirection.... If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.
Curiously, I don't see any discussion of this change in the C99 Rationale, though I may just be not finding it.

Why can this C code run correctly? [duplicate]

This question already has answers here:
Why does sizeof(x++) not increment x?
(10 answers)
Closed 7 years ago.
The C code likes this:
#include <stdio.h>
#include <unistd.h>
#define DIM(a) (sizeof(a)/sizeof(a[0]))
struct obj
{
int a[1];
};
int main()
{
struct obj *p = NULL;
printf("%d\n",DIM(p->a));
return 0;
}
This object pointer p is NULL, so, i think this p->a is illegal.
But i have tested this code in Ubuntu14.04, it can execute correctly. So, I want to know why...
Note: the original code had int a[0] above but I've changed that to int a[1] since everyone seems to be hung up on that rather than the actual question, which is:
Is the expression sizeof(p->a) valid when p is equal to NULL?
Because sizeof is a compile time construction, it does not depend on evaluating the input. sizeof(p->a) gets evaluated based on the declared type of the member p::a solely, and becomes a constant in the executable. So the fact that p points to null makes no difference.
The runtime value of p plays absolutely no role in the expression sizeof(p->a).
In C and C++, sizeof is an operator and not a function. It can be applied to either a type-id or an expression. Except in the case that of an expression and the expression is a variable-length array (new in C99) (as pointed out by paxdiablo), the expression is an unevaluated operand and the result is the same as if you had taken sizeof against the type of that expression instead. (C.f. C11 references due to paxdiablo below, C++14 working draft 5.3.3.1)
First up, if you want truly portable code, you shouldn't be attempting to create an array of size zero1, as you did in your original question, now fixed. But, since it's not really relevant to your question of whether sizeof(p->a) is valid when p == NULL, we can ignore it for now.
From C11 section 6.5.3.4 The sizeof and _Alignof operators (my bold):
2/ 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.
Therefore no evaluation of the operand is done unless it's a variable length array (which your example is not). Only the type itself is used to figure out the size.
1 For the language lawyers out there, C11 states in 6.7.6.2 Array declarators (my bold):
1/ In addition to optional type qualifiers and the keyword static, the [ and ] may delimit an expression or *. If they delimit an expression (which specifies the size of an array), the expression shall have an integer type. If the expression is a constant expression, it shall have a value greater than zero.
However, since that's in the constraints section (where shall and shall not do not involve undefined behaviour), it simply means the program itself is not strictly conforming. It's still covered by the standard itself.
This code contains a constraint violation in ISO C because of:
struct obj
{
int a[0];
};
Zero-sized arrays are not permitted anywhere. Therefore the C standard does not define the behaviour of this program (although there seems to be some debate about that).
The code can only "run correctly" if your compiler implements a non-standard extension to allow zero-sized arrays.
Extensions must be documented (C11 4/8), so hopefully your compiler's documentation defines its behaviour for struct obj (a zero-sized struct?) and the value of sizeof p->a, and whether or not sizeof evaluates its operand when the operand denotes a zero-sized array.
sizeof() doesn't care a thing about the content of anything, it merely looks at the resulting type of the expression.
Since C99 and variable length arrays, it is computed at run time when a variable length array is part of the expression in the sizeof operand.Otherwise, the operand is not evaluated and the result is an integer constant
Zero-size array declarations within structs was never permitted by any C standard, but some older compilers allowed it before it became standard for compilers to allow incomplete array declarations with empty brackets(flexible array members).

Do parentheses make a difference when determining the size of an array?

The following program prints the same number twice on gcc 4.8.2:
#include <stdio.h>
int main()
{
char a[13];
printf("sizeof a is %zu\n", sizeof a );
printf("sizeof(a) is %zu\n", sizeof(a));
}
According to this reddit post, gcc is not standard-conformant in this respect, because a parenthesized expression is not on the list of exceptions for when array-to-pointer decay does not happen.
Is this guy correct? Here is the relevant standard quote:
Except when it is the operand of the sizeof operator or the unary & operator, or is a character string literal used to initialize an array of character type, or is a wide string literal used to initialize an array with element type compatible with wchar_t, an lvalue that has type 'array of type' is converted to an expression that has type 'pointer to type' that points to the initial member of the array object and is not an lvalue.
Just to be clear, he argues that (a) should trigger array-to-pointer decay, because parentheses are not covered in the list above (sizeof operator, unary & operator, string literal as initializer).
Whether seemingly redundant parentheses affect the semantics of a program is a long-standing issue in the C standard that still hasn't been adequately resolved.
It is commonly claimed that ((void*)0) is technically not a null pointer constant, because there is no rule that says a parenthesised null pointer constant is a null pointer constant.
Some compilers issue an error for char s[] = ("abc");, because while a character array can be initialised from a string literal, that rule doesn't cover parenthesised string literals.
There are many similar examples. You've found one of them.
From what I can tell, the concensus is basically that the rule should be what C++ does, but what C never formally adopted. C++ makes a parenthesised expression functionally equivalent to the non-parenthesised expression, with a few explicitly-stated exceptions. This would cover all those issues at once.
So technically, the guy could be considered correct, but it's an overly strict interpretation of the standard that nobody really follows, since it's common knowledge that the standard is simply faulty here.
From C99, 6.5.1, on parenthesized expressions:
Its type and value are identical to those of the unparenthesized expression.
At first glance, it would appear that this conflicts with the exception list you're referring to (6.3.2.1):
Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type "array of type" is converted to an expression with type "pointer to type"...
However, this list is in the context of operators/operands; parentheses don't appear to be deemed an operator (based on the categorisation implied by the structure of section 6.5).

Why is sizeof considered an operator?

Why is sizeof considered an operator and not a function?
What property is necessary to qualify as an operator?
Because the C standard says so, and it gets the only vote.
As consequences:
The operand of sizeof can be a parenthesised type, sizeof (int), instead of an object expression.
The parentheses are unnecessary: int a; printf("%d\n", sizeof a); is perfectly fine. They're often seen, firstly because they're needed as part of a type cast expression, and secondly because sizeof has very high precedence, so sizeof a + b isn't the same as sizeof (a+b). But they aren't part of the invocation of sizeof, they're part of the operand.
You can't take the address of sizeof.
The expression which is the operand of sizeof is not evaluated at runtime (sizeof a++ does not modify a).
The expression which is the operand of sizeof can have any type except void, or function types. Indeed, that's kind of the point of sizeof.
A function would differ on all those points. There are probably other differences between a function and a unary operator, but I think that's enough to show why sizeof could not be a function even if there was a reason to want it to be.
It can be used as a compile-time constant, which is only possible if it's an operator rather than a function. For instance:
union foo {
int i;
char c[sizeof(int)];
};
Syntactically if it weren't an operator then it would have to be a preprocessor macro since functions can't take types as arguments. That would be a difficult macro to implement since sizeof can take both types and variables as an argument.
Because the C standard says so, and it gets the only vote.
And the standard is probably correct because sizeof takes a type and
In general, if either the domain or codomain (or both) of a function contains elements significantly more complex than real numbers, that function is referred to as an operator. Conversely, if neither the domain nor the codomain of a function contain elements more complicated than real numbers, that function is likely to be referred to simply as a function. Trigonometric functions such as cosine are examples of the latter case.
Additionally, when functions are used so often that they have evolved faster or easier notations than the generic F(x,y,z,...) form, the resulting special forms are also called operators. Examples include infix operators such as addition "+" and division "/", and postfix operators such as factorial "!". This usage is unrelated to the complexity of the entities involved.
(Wikipedia)
Because it's not a function. You can use it like that:
int a;
printf("%d\n", sizeof a);
Function does have entry point, code, etc. Function is to be run at runtime (or inlined), sizeof has to be determined at compile-time.
sizeof operator is compile time entity not runtime and don't need parenthesis like a function. When code is compiled then it replace the value with the size of that variable at compile time but in function after function gets execute then we will know the returning value.
Because:
when you pass a value to a function, the size of the object is not passed to the function, so a sizeof "function" would have no way of determining the size
in C, functions can only accept one type of argument; sizeof() needs to accept all sorts of differnet things (variables as well as types! You can't pass a type to a function in C)
calling a function involves making a copy of the arguments and other unnecessary overhead
There is small diference from function - value of sizeof is resolved on compile time, but not at runtime!
Because it is a compile-time operator that, in order to calculate the size of an object, requires type information that is only available at compile-time. This doesn't hold for C++.
sizeof() operator is a compile time would be occurrence. It can be used to determine the parameters or arguments.
Sizeof(), I think obviously it's both a function and an operator. Why? Because a function holds parentheses for entry at the stage of entry. But mainly also an operator cause operators are action character, therefore sizeof is an action statement that acts on the operand in the parentheses.

Resources