#include<iostream>
using namespace std;
int main()
{
int *p,*c;
p=(int*)10;
c=(int*)20;
cout<<(int)p<<(int)c;
}
Somebody asked me "What is wrong with the above code?" and I couldn't figure it out. Someone please help me.
The fact that int and pointer data types are not required to have the same number of bits, according to the C++ standard, is one thing - that means you could lose precision.
In addition, casting an int to an int pointer then back again is silly. Why not just leave it as an int?
I actually did try to compile this under gcc and it worked fine but that's probably more by accident than good design.
Some wanted a quote from the C++ standard (I'd have put this in the comments of that answer if the format of comments wasn't so restricted), here are two from the 1999 one:
5.2.10/3
The mapping performed by reinterpret_cast is implementation defined.
5.2.10/5
A value of integral type or enumeration type can be explicitly converted to a pointer.
A pointer converted to an integer of sufficient size (if ant such exists on the implementation)
and back to the same pointer type will have its original value; mappings between pointers and
integers are otherwise implementation-defined.
And I see nothing mandating that such implementation-defined mapping must give a valid representation for all input. Otherwise said, an implementation on an architecture with address registers can very well trap when executing
p = (int*)10;
if the mapping does not give a representation valid at that time (yes, what is a valid representation for a pointer may depend of time. For instance delete may make invalid the representation of the deleted pointer).
Assuming I'm right about what this is supposed to be, it should look like this:
int main()
{
int *p, *c;
// Something that creates whatever p and c point to goes here, a trivial example would be.
int pValue, cValue;
p = &pValue;
c = &cValue;
// The & operator retrieves the memory address of pValue and cValue.
*p = 10;
*c = 20;
cout << *p << *c;
}
In order to assign or retrieve a value to a variable referenced by a pointer, you need to dereference it.
What your code is doing is casting 10 into pointer to int (which is the memory address where the actual int resides).
addresses p and c may be larger than int.
The problem on some platforms you need
p = (int*) (long) 10;
See GLIB documentation on type conversion macros.
And for the people who might not find a use for this type of expressions, it is possible to return data inside pointer value returning functions. You can find real-world examples, where this case it is better to use this idiom, instead of allocating a new integer on the heap, and return it back - poor performance, memory fragmentation, just ugly.
You're assigning values (10 and 20) to the pointers which obviously is a potential problem if you try to read the data at those addresses. Casting the pointer to an integer is also really ugly. And your main function does not have a return statement. That is just a few things.
there is more or less everything wrong with it:
int *p,*c;
p=(int*)10;
c=(int*)20;
afterwards p is pointing to memory address 10
afterwards c is pointing to memory address 20
This doesn't look very intentional.
And I suppose that the whole program will simply crash.
Related
I have searched and searched for an answer to this but can't find anything I actually "get".
I am very very new to c++ and can't get my head around the use of double, triple pointers etc.. What is the point of them?
Can anyone enlighten me
Honestly, in well-written C++ you should very rarely see a T** outside of library code. In fact, the more stars you have, the closer you are to winning an award of a certain nature.
That's not to say that a pointer-to-pointer is never called for; you may need to construct a pointer to a pointer for the same reason that you ever need to construct a pointer to any other type of object.
In particular, I might expect to see such a thing inside a data structure or algorithm implementation, when you're shuffling around dynamically allocated nodes, perhaps?
Generally, though, outside of this context, if you need to pass around a reference to a pointer, you'd do just that (i.e. T*&) rather than doubling up on pointers, and even that ought to be fairly rare.
On Stack Overflow you're going to see people doing ghastly things with pointers to arrays of dynamically allocated pointers to data, trying to implement the least efficient "2D vector" they can think of. Please don't be inspired by them.
In summary, your intuition is not without merit.
An important reason why you should/must know about pointer-to-pointer-... is that you sometimes have to interface with other languages (like C for instance) through some API (for instance the Windows API).
Those APIs often have functions that have an output-parameter that returns a pointer. However those other languages often don't have references or compatible (with C++) references. That's a situation when pointer-to-pointer is needed.
It's less used in c++. However, in C, it can be very useful. Say that you have a function that will malloc some random amount of memory and fill the memory with some stuff. It would be a pain to have to call a function to get the size you need to allocate and then call another function that will fill the memory. Instead you can use a double pointer. The double pointer allows the function to set the pointer to the memory location. There are some other things it can be used for but that's the best thing I can think of.
int func(char** mem){
*mem = malloc(50);
return 50;
}
int main(){
char* mem = NULL;
int size = func(&mem);
free(mem);
}
I am very very new to c++ and can't get my head around the use of double, triple pointers etc.. What is the point of them?
The trick to understanding pointers in C is simply to go back to the basics, which you were probably never taught. They are:
Variables store values of a particular type.
Pointers are a kind of value.
If x is a variable of type T then &x is a value of type T*.
If x evaluates to a value of type T* then *x is a variable of type T. More specifically...
... if x evaluates to a value of type T* that is equal to &a for some variable a of type T, then *x is an alias for a.
Now everything follows:
int x = 123;
x is a variable of type int. Its value is 123.
int* y = &x;
y is a variable of type int*. x is a variable of type int. So &x is a value of type int*. Therefore we can store &x in y.
*y = 456;
y evaluates to the contents of variable y. That's a value of type int*. Applying * to a value of type int* gives a variable of type int. Therefore we can assign 456 to it. What is *y? It is an alias for x. Therefore we have just assigned 456 to x.
int** z = &y;
What is z? It's a variable of type int**. What is &y? Since y is a variable of type int*, &y must be a value of type int**. Therefore we can assign it to z.
**z = 789;
What is **z? Work from the inside out. z evaluates to an int**. Therefore *z is a variable of type int*. It is an alias for y. Therefore this is the same as *y, and we already know what that is; it's an alias for x.
No really, what's the point?
Here, I have a piece of paper. It says 1600 Pennsylvania Avenue Washington DC. Is that a house? No, it's a piece of paper with the address of a house written on it. But we can use that piece of paper to find the house.
Here, I have ten million pieces of paper, all numbered. Paper number 123456 says 1600 Pennsylvania Avenue. Is 123456 a house? No. Is it a piece of paper? No. But it is still enough information for me to find the house.
That's the point: often we need to refer to entities through multiple levels of indirection for convenience.
That said, double pointers are confusing and a sign that your algorithm is insufficiently abstract. Try to avoid them by using good design techniques.
A double-pointer, is simply a pointer to a pointer. A common usage is for arrays of character strings. Imagine the first function in just about every C/C++ program:
int main(int argc, char *argv[])
{
...
}
Which can also be written
int main(int argc, char **argv)
{
...
}
The variable argv is a pointer to an array of pointers to char. This is a standard way of passing around arrays of C "strings". Why do that? I've seen it used for multi-language support, blocks of error strings, etc.
Don't forget that a pointer is just a number - the index of the memory "slot" inside a computer. That's it, nothing more. So a double-pointer is index of a piece of memory that just happens to hold another index to somewhere else. A mathematical join-the-dots if you like.
This is how I explained pointers to my kids:
Imagine the computer memory is a series of boxes. Each box has a number written on it, starting at zero, going up by 1, to however many bytes of memory there is. Say you have a pointer to some place in memory. This pointer is just the box number. My pointer is, say 4. I look into box #4. Inside is another number, this time it's 6. So now we look into box #6, and get the final thing we wanted. My original pointer (that said "4") was a double-pointer, because the content of its box was the index of another box, rather than being a final result.
It seems in recent times pointers themselves have become a pariah of programming. Back in the not-too-distant past, it was completely normal to pass around pointers to pointers. But with the proliferation of Java, and increasing use of pass-by-reference in C++, the fundamental understanding of pointers declined - particularly around when Java became established as a first-year computer science beginners language, over say Pascal and C.
I think a lot of the venom about pointers is because people just don't ever understand them properly. Things people don't understand get derided. So they became "too hard" and "too dangerous". I guess with even supposedly learned people advocating Smart Pointers, etc. these ideas are to be expected. But in reality there a very powerful programming tool. Honestly, pointers are the magic of programming, and after-all, they're just a number.
In many situations, a Foo*& is a replacement for a Foo**. In both cases, you have a pointer whose address can be modified.
Suppose you have an abstract non-value type and you need to return it, but the return value is taken up by the error code:
error_code get_foo( Foo** ppfoo )
or
error_code get_foo( Foo*& pfoo_out )
Now a function argument being mutable is rarely useful, so the ability to change where the outermost pointer ppFoo points at is rarely useful. However, a pointer is nullable -- so if get_foo's argument is optional, a pointer acts like an optional reference.
In this case, the return value is a raw pointer. If it returns an owned resource, it should usually be instead a std::unique_ptr<Foo>* -- a smart pointer at that level of indirection.
If instead, it is returning a pointer to something it does not share ownership of, then a raw pointer makes more sense.
There are other uses for Foo** besides these "crude out parameters". If you have a polymorphic non-value type, non-owning handles are Foo*, and the same reason why you'd want to have an int* you would want to have a Foo**.
Which then leads you to ask "why do you want an int*?" In modern C++ int* is a non-owning nullable mutable reference to an int. It behaves better when stored in a struct than a reference does (references in structs generate confusing semantics around assignment and copy, especially if mixed with non-references).
You could sometimes replace int* with std::reference_wrapper<int>, well std::optional<std::reference_wrapper<int>>, but note that is going to be 2x as large as a simple int*.
So there are legitimate reasons to use int*. Once you have that, you can legitimately use Foo** when you want a pointer to a non-value type. You can even get to int** by having a contiguous array of int*s you want to operate on.
Legitimately getting to three-star programmer gets harder. Now you need a legitimate reason to (say) want to pass a Foo** by indirection. Usually long before you reach that point, you should have considered abstracting and/or simplifying your code structure.
All of this ignores the most common reason; interacting with C APIs. C doesn't have unique_ptr, it doesn't have span. It tends to use primitive types instead of structs because structs require awkward function based access (no operator overloading).
So when C++ interacts with C, you sometimes get 0-3 more *s than the equivalent C++ code would.
The use is to have a pointer to a pointer, e.g., if you want to pass a pointer to a method by reference.
What real use does a double pointer have?
Here is practical example. Say you have a function and you want to send an array of string params to it (maybe you have a DLL you want to pass params to). This can look like this:
#include <iostream>
void printParams(const char **params, int size)
{
for (int i = 0; i < size; ++i)
{
std::cout << params[i] << std::endl;
}
}
int main()
{
const char *params[] = { "param1", "param2", "param3" };
printParams(params, 3);
return 0;
}
You will be sending an array of const char pointers, each pointer pointing to the start of a null terminated C string. The compiler will decay your array into pointer at function argument, hence what you get is const char ** a pointer to first pointer of array of const char pointers. Since the array size is lost at this point, you will want to pass it as second argument.
One case where I've used it is a function manipulating a linked list, in C.
There is
struct node { struct node *next; ... };
for the list nodes, and
struct node *first;
to point to the first element. All the manipulation functions take a struct node **, because I can guarantee that this pointer is non-NULL even if the list is empty, and I don't need any special cases for insertion and deletion:
void link(struct node *new_node, struct node **list)
{
new_node->next = *list;
*list = new_node;
}
void unlink(struct node **prev_ptr)
{
*prev_ptr = (*prev_ptr)->next;
}
To insert at the beginning of the list, just pass a pointer to the first pointer, and it will do the right thing even if the value of first is NULL.
struct node *new_node = (struct node *)malloc(sizeof *new_node);
link(new_node, &first);
Multiple indirection is largely a holdover from C (which has neither reference nor container types). You shouldn't see multiple indirection that much in well-written C++, unless you're dealing with a legacy C library or something like that.
Having said that, multiple indirection falls out of some fairly common use cases.
In both C and C++, array expressions will "decay" from type "N-element array of T" to "pointer to T" under most circumstances1. So, assume an array definition like
T *a[N]; // for any type T
When you pass a to a function, like so:
foo( a );
the expression a will be converted from "N-element array of T *" to "pointer to T *", or T **, so what the function actually receives is
void foo( T **a ) { ... }
A second place they pop up is when you want a function to modify a parameter of pointer type, something like
void foo( T **ptr )
{
*ptr = new_value();
}
void bar( void )
{
T *val;
foo( &val );
}
Since C++ introduced references, you probably won't see that as often. You'll usually only see that when working with a C-based API.
You can also use multiple indirection to set up "jagged" arrays, but you can achieve the same thing with C++ containers for much less pain. But if you're feeling masochistic:
T **arr;
try
{
arr = new T *[rows];
for ( size_t i = 0; i < rows; i++ )
arr[i] = new T [size_for_row(i)];
}
catch ( std::bad_alloc& e )
{
...
}
But most of the time in C++, the only time you should see multiple indirection is when an array of pointers "decays" to a pointer expression itself.
The exceptions to this rule occur when the expression is the operand of the sizeof or unary & operator, or is a string literal used to initialize another array in a declaration.
In C++, if you want to pass a pointer as an out or in/out parameter, you pass it by reference:
int x;
void f(int *&p) { p = &x; }
But, a reference can't ("legally") be nullptr, so, if the pointer is optional, you need a pointer to a pointer:
void g(int **p) { if (p) *p = &x; }
Sure, since C++17 you have std::optional, but, the "double pointer" has been idiomatic C/C++ code for many decades, so should be OK. Also, the usage is not so nice, you either:
void h(std::optional<int*> &p) { if (p) *p = &x) }
which is kind of ugly at the call site, unless you already have a std::optional, or:
void u(std::optional<std::reference_wrapper<int*>> p) { if (p) p->get() = &x; }
which is not so nice in itself.
Also, some might argue that g is nicer to read at the call site:
f(p);
g(&p); // `&` indicates that `p` might change, to some folks
Is there a difference between pointer to integer-pointer (int**) and pointer to character-pointer (char**), and any other case of pointer to pointer?
Isn't the memory block size for any pointer is the same, so the sub-datatype doesn't play a role in here?
Is it just a semantic distinction with no other significance?
Why not to use just void**?
Why should we use void** when you want a pointer to a char *? Why should we not use char **?
With char **, you have type safety. If the pointer is correctly initialized and not null, you know that by dereferencing it once you get a valid char * - and by dereferencing that pointer, in turn, you get a char.
Why should you ignore this advantage in type safety, and instead play pointer Russian roulette with void**?
The difference is in type-safety. T** implicitly interprets the data as T. void**, however, needs to be manually casted first. And no, pointers are not all 4 / 8 bytes on 32 / 64bit architectures respectively. Member function pointers, for instance, contain offset information too, which needs to be stored in the pointer itself (in the most common implementation).
Most C implementations use the same size and format for all pointers, but this is not required by the C standard.
Some machines do not have byte addressing, so the C implementation implements it by using shifts and other operations. In these implementations, pointers to larger types, such as int, may be normal addresses, but pointers to char would have to have both a machine address and a byte-within-word offset.
Additionally, C makes use of the type information for a variety of purposes, including reducing mistakes made by programmers (possibly giving warnings or errors when you attempt to use a pointer to int where a pointer to float is needed) and optimization. Regarding optimization, consider this example:
void foo(float *array, int *limit)
{
for (int i = 0; i < *limit; ++i)
array[i] = <some calculation>;
}
The C standard says a compiler may use the fact that array and limit are pointers to different types to conclude that they do not overlap. Given this rule, the C implementation may evaluate *limit once when the loop starts, because it knows it will not change during the loop. Without this rule, the compiler would have to assume that one of the assignments to array[i] might change *limit, and it would have to load *limit from memory in each iteration.
int *p;
scanf("%d",&p);
printf("%d\n",p);
In my past understandings,the "p" is a address,but now it seems that the p is a simple variable.
I cant understand why these 3 lines code are right!!!
can you help me?
This will only work as long as a pointer is the same size as an integer because you are basically treating the pointer as an integer. That is, if int is a 32-bit integer, and a pointer void* is a 32-bit address.
The way it should be written:
int p; // not the lack of the *
scanf("%d",&p); // this gives scanf the address of p
printf("%d\n",p); // this uses p's value
Which will actually use p as an integer instead of declaring it as a pointer and treating it like an integer.
They are not right. They just seem to work, because you ask scanf to store an integer and the address where to store it is the address of the pointer p. You are basically treating the storage of the pointer itself as the storage of an integer. Likewise for printf, you pass the address of the pointer (which contains the integer) and ask printf to read it from there as... an integer. You could even change the first line to
float* p;
and it would still seem to work. In the end, this is a good example of why you should avoid C-style interfaces which are not type-safe.
If I will explain through your statements, then it will be
int *p; //Declaration of pointer variable p, which can hold the address of integer variable
scanf("%d",&p); //Getting input, will be stored at address of pointer variable p
printf("%d\n",p); //It will display the value stored at &p
The code above is not really correct, and it is built on top of a fair amount of assumptions and C constructs.
The first assumption is that a pointer and an int have the same size, which will break in most (all I know) 64bit platforms. It is then using a type unsafe interface (variadic function arguments) to pass the address of an int* as if it was the address of an int. The code inside the scanf will assume that it is writting to an int and write over the bits... but the type is not an int* and that bit pattern might or not make sense even in the platforms where the sizeof(int) = sizeof(int*)
That code is not right at all.
Some (bad) compilers may be unable to detect the problems because both printf and scanf are variadic functions... but for example g++ would warn you that the types passed don't match with the ones specified in the format strings.
Consider this code:
int *p = new int;
cout << sizeof(*p);
delete p;
As expected the result is 4. Now, consider this other code:
int *p = new int[10];
cout << sizeof(*p);
delete[] p;
I expected to get 40 (the size of the allocated array), however the result is still 4.
Now, suppose I have a function int *foo() that returns a pointer to a structure created with new or with new[] (but I don't know which one):
int *p = foo();
My question is, is there a way (or hack) to know if p points to a single integer or an array of integers?
Please keep in mind that this is just a theoretical question. I won't be writing real code in this fashion.
No, there is no way of doing that. But you know the difference, because the code you wrote called new or new[].
The reason by the way that:
cout << sizeof(*p);
gives you 4 in both cases is because p is a pointer to an int, the expression *p means the thing pointed to by such a pointer (i.e. an int) and the size of an int on your platform is 4. This is all evaluated at compile time, so even if new[] did return a special value, sizeof would not be able to use it.
No, because your result is an address (that's why you get 4 for sizeof() in both cases). You created it, so you're expected to know what it is.
In both examples the type of p is the same: int *. sizeof operates on the type, not the data. It's computed at compile time.
You have a couple of choices. You can keep track of the array size yourself, or you can venture into using one of the containers in the standard library such as vector< int >. These containers will track the size (e.g. vector< int >::size()) for you.
sizeof(x) returns the amount of memory needed to contain x as declared.
There is no dynamic aspect to this at all.
sizeof (*foo) where foo is a bar * will always be the same as sizeof(bar)
No, there isn't any way.
Obligatory question: Why do you need to know?
If it's "because I need to know whether to say delete [] or delete", then just use arrays all the time, if for some obscure reason you can't figure out which one you used in your own code.
Having a function that can return a pointer to a single item or an array is a bad design decision. You can always return a pointer to an array of size 1:
return new int[1];
First, sizeof(*p) returns always a value to the integer, so it's always returning 4.
Now, how can you know whether p is pointing to int or int[] ?
There is no standard way of it. However, you can hack the platform and get it known. For example, if you try printing p[-1], p[-2], ..., p[-4] etc. for certain compilers (say linux in my case) then you will see a particular pattern in the value of this locations. However, this is just a hack and you cannot rely upon it always.
Originally being the topic of this question, it emerged that the OP just overlooked the dereference. Meanwhile, this answer got me and some others thinking - why is it allowed to cast a pointer to a reference with a C-style cast or reinterpret_cast?
int main() {
char c = 'A';
char* pc = &c;
char& c1 = (char&)pc;
char& c2 = reinterpret_cast<char&>(pc);
}
The above code compiles without any warning or error (regarding the cast) on Visual Studio while GCC will only give you a warning, as shown here.
My first thought was that the pointer somehow automagically gets dereferenced (I work with MSVC normally, so I didn't get the warning GCC shows), and tried the following:
#include <iostream>
int main() {
char c = 'A';
char* pc = &c;
char& c1 = (char&)pc;
std::cout << *pc << "\n";
c1 = 'B';
std::cout << *pc << "\n";
}
With the very interesting output shown here. So it seems that you are accessing the pointed-to variable, but at the same time, you are not.
Ideas? Explanations? Standard quotes?
Well, that's the purpose of reinterpret_cast! As the name suggests, the purpose of that cast is to reinterpret a memory region as a value of another type. For this reason, using reinterpret_cast you can always cast an lvalue of one type to a reference of another type.
This is described in 5.2.10/10 of the language specification. It also says there that reinterpret_cast<T&>(x) is the same thing as *reinterpret_cast<T*>(&x).
The fact that you are casting a pointer in this case is totally and completely unimportant. No, the pointer does not get automatically dereferenced (taking into account the *reinterpret_cast<T*>(&x) interpretation, one might even say that the opposite is true: the address of that pointer is automatically taken). The pointer in this case serves as just "some variable that occupies some region in memory". The type of that variable makes no difference whatsoever. It can be a double, a pointer, an int or any other lvalue. The variable is simply treated as memory region that you reinterpret as another type.
As for the C-style cast - it just gets interpreted as reinterpret_cast in this context, so the above immediately applies to it.
In your second example you attached reference c to the memory occupied by pointer variable pc. When you did c = 'B', you forcefully wrote the value 'B' into that memory, thus completely destroying the original pointer value (by overwriting one byte of that value). Now the destroyed pointer points to some unpredictable location. Later you tried to dereference that destroyed pointer. What happens in such case is a matter of pure luck. The program might crash, since the pointer is generally non-defererencable. Or you might get lucky and make your pointer to point to some unpredictable yet valid location. In that case you program will output something. No one knows what it will output and there's no meaning in it whatsoever.
One can rewrite your second program into an equivalent program without references
int main(){
char* pc = new char('A');
char* c = (char *) &pc;
std::cout << *pc << "\n";
*c = 'B';
std::cout << *pc << "\n";
}
From the practical point of view, on a little-endian platform your code would overwrite the least-significant byte of the pointer. Such a modification will not make the pointer to point too far away from its original location. So, the code is more likely to print something instead of crashing. On a big-endian platform your code would destroy the most-significant byte of the pointer, thus throwing it wildly to point to a totally different location, thus making your program more likely to crash.
It took me a while to grok it, but I think I finally got it.
The C++ standard specifies that a cast reinterpret_cast<U&>(t) is equivalent to *reinterpret_cast<U*>(&t).
In our case, U is char, and t is char*.
Expanding those, we see that the following happens:
we take the address of the argument to the cast, yielding a value of type char**.
we reinterpret_cast this value to char*
we dereference the result, yielding a char lvalue.
reinterpret_cast allows you to cast from any pointer type to any other pointer type. And so, a cast from char** to char* is well-formed.
I'll try to explain this using my ingrained intuition about references and pointers rather than relying on the language of the standard.
C didn't have reference types, it only had values and pointer types (addresses) - since, physically in memory, we only have values and addresses.
In C++ we've added references to the syntax, but you can think of them as a kind of syntactic sugar - there is no special data structure or memory layout scheme for holding references.
Well, what "is" a reference from that perspective? Or rather, how would you "implement" a reference? With a pointer, of course. So whenever you see a reference in some code you can pretend it's really just a pointer that's been used in a special way: if int x; and int& y{x}; then we really have a int* y_ptr = &x; and if we say y = 123; we merely mean *(y_ptr) = 123;. This is not dissimilar from how, when we use C array subscripts (a[1] = 2;) what actually happens is that a is "decayed" to mean pointer to its first element, and then what gets executed is *(a + 1) = 2.
(Side note: Compilers don't actually always hold pointers behind every reference; for example, the compiler might use a register for the referred-to variable, and then a pointer can't point to it. But the metaphor is still pretty safe.)
Having accepted the "reference is really just a pointer in disguise" metaphor, it should now not be surprising that we can ignore this disguise with a reinterpret_cast<>().
PS - std::ref is also really just a pointer when you drill down into it.
Its allowed because C++ allows pretty much anything when you cast.
But as for the behavior:
pc is a 4 byte pointer
(char)pc tries to interpret the pointer as a byte, in particular the last of the four bytes
(char&)pc is the same, but returns a reference to that byte
When you first print pc, nothing has happened and you see the letter you stored
c = 'B' modifies the last byte of the 4 byte pointer, so it now points to something else
When you print again, you are now pointing to a different location which explains your result.
Since the last byte of the pointer is modified the new memory address is nearby, making it unlikely to be in a piece of memory your program isn't allowed to access. That's why you don't get a seg-fault. The actual value obtained is undefined, but is highly likely to be a zero, which explains the blank output when its interpreted as a char.
when you're casting, with a C-style cast or with a reinterpret_cast, you're basically telling the compiler to look the other way ("don't you mind, I know what I'm doing").
C++ allows you to tell the compiler to do that. That doesn't mean it's a good idea...