hi,

int arr[2][2][2]={1,2,3,4,5,6,7,8}:
int *p,*q;

q=(int*)arr;

printf("%d",*q);

my question is that how is it giving output as "1"(ofcourse, without quotes). what will change if i don't typecast arr in 3rd line of code? will anyone please explain.Is it giving o/p "1" ,just because of that typecast ?

my thinking: as arr can be viewed as the pointer to a array of pointers. so giving just *arr or q=arr will not give the value of the first element of array. right ? we must do **q in that case for printing first value of array. I think we are getting "1" here just because of some reason(which i want to know from somebody here) of that typecast in 3rd line. make me correct in my thinking if i am wrong.

thanks. any help will be thankful.

Edited 4 Years Ago by I_m_rude

I_m_rude
Deleted Member

The address produced by using arr in value context is then reinterpreted as a pointer to int, which can then be dereferenced to get the value stored at arr[0][0][0]. This particular cast is safe, at least until you decide to iterate over all of the items:

int arr[2][2][2] = {1, 2, 3, 4, 5, 6, 7, 8};
int *q = (int*)arr;
int i;

/* Please don't do this */
for (i = 0; i < 8; ++i)
    printf("%d\n", *q++);

While this type of punning of multidimensional arrays into 1D arrays usually works, it's technically undefined by the C standard.

so this type of typecasting (int*) here, is undefined or defined ? i mean is it good to do or not ?

The cast is defined. The way you use the resulting pointer could be defined or undefined. I wouldn't call it good or bad, but the cast does raise warning flags such that I'd question it in a code review.

what will happen if i dn't type cast it and everything is same in code ?

I didn't get one point that how can typecasting an pointer to an array of pinters into an integer pointer make it to point to the forst element in the array ? Can you throw light on this!

I didn't get one point that how can typecasting an pointer to an array of pinters into an integer pointer make it to point to the forst element in the array ?

You know that array indexing is essentially an offset from the base address of the array, right? So a[5] is equivalent to converting a to a pointer to the first element, then incrementing the pointer by 5 and dereferencing the result (ie. *(a + 5)). Well, all arrays work like that, and the base address is always the first element of the most nested dimension.

So regardless of how you interpret the address, it's always the same address. For example:

#include <stdio.h>

int main(void)
{
    int a[2][3][4];

    printf("%p\n", (void*)a);
    printf("%p\n", (void*)a[0]);
    printf("%p\n", (void*)a[0][0]);
    printf("%p\n", (void*)&a[0][0][0]);

    return 0;
}

but this is the case with first element of array .. right ?

In array pointers, when you are not specifying any index of the array it takes the first position as default. Unless untill you give specific index to the array,it returns the value of first index pointer. You would get the same output if you typecast or not.

In array pointers, when you are not specifying any index of the array it takes the first position as default. Unless untill you give specific index to the array,it returns the value of first index p

.

Edited 4 Years Ago by phani1092: missed one point

but deceptikon said that typecast is neccassary in this case, otherwise nature will be undefined. what is the exaclt answer for this ?

but deceptikon said that typecast is neccassary in this case, otherwise nature will be undefined.

I said that the typecast is safe, but use of the resulting pointer could potentially be undefined. However, phani1092 is incorrect in saying that the cast isn't necessary because you have to either conform to C's type system or subvert it. If you want to assign a naked 2D array to a pointer to int (as in the original example), you must subvert the type system with a cast. If you want to conform to the type system, you must use the correct destination type:

int arr[2][2][2] = {1, 2, 3, 4, 5, 6, 7, 8};
int (*q)[2][2] = arr;

Now deceptikon, nitin1 asked about the first element of the array and for first element there is no need to type cast,if it would have been necessary the compiler would have thrown definite error.

Now deceptikon, nitin1 asked about the first element of the array and for first element there is no need to type cast,if it would have been necessary the compiler would have thrown definite error.

Try to compile the following code and enjoy the definite error along the lines of "cannot convert 'int (*)[2][2]' to 'int*'":

#include <stdio.h>

int main(void)
{
    int arr[2][2][2];
    int *p = arr;

    printf("%d", *p);

    return 0;
}

You clearly don't know what you're talking about. Since nitin1 gets confused easily, please stop replying with incorrect information. In fact, you should read my replies carefully and do a bit of learning yourself.

#include <stdio.h>

int main(void)
{
    int arr[2][2][2]={1,2,3,4,5,6,7,8};
    int *p = arr;

    printf("%d", *p);

    return 0;
}

Try compiling this you will get what i am talking about. 

Codepad is wrong, probably because it doesn't use appropriate flags for strict compilation as C. AT the very least there should be a warning.

@deceptikon tell me one thing now.

int arr[2][2][2] = {1, 2, 3, 4, 5, 6, 7, 8};
int (*q)[2][2] = arr;

In your code, can i say these 2 statements ?

1.arr is a pointer to an array of 2 elements in which each element is a pointer to a 2-D array.
2. q is a pointer to an 2-D array.

Are they right ?

If Yes, then how arr is assigned to the q which is a pointer to only 2-D array , not to the array of 2-D arrays. I hope i am clear in my question.
if i am wrong, can you give me tips or tell how to visualize these type pf things like 3-D arrays or pointer to the 2-D arrays ? please explain.
thanks.

Edited 4 Years Ago by I_m_rude

You haven't got 1 quite right, arr is not "a pointer to an array of 2 elements in which each element is a pointer to a 2-D array" but rather the expression arr evaluates to a pointer to the first element in an array of 2 elements in which each element is an array of 2 elements of an array of 2 ints. It is a little complex because C does not properly have 2 or more dimensional arrays but rather arrays of arrays (I admit the difference is subtle at times).

The easiest way I know to visualise these things is this

  1. Start with the array definition int arr[2][2][2]
  2. Remove the [] brackets furtherst to the right int arr[2][2]
  3. Repace the symbol name with (*) int (*)[2][2]
  4. That is your type if you want a symbol name add it immediately after the * int (*q)[2][2]

This will produce the correct type to allow an assigment without a cast as you have in your most recent code. You can then read the type int (*)[2][2] as

A pointer ((*)) to an array of 2 elements (right hand [2]) where each element is an array of 2 (left hand [2]) integers (int).

@banfa Can u please again explain the point which is the difference between my thinking and your explaination of that first point. means how am i wrong and how are you correct ? please tell(explain i must say) . arr evaluates to a pointer, you said and i said, arr is a pointer. What is difference in that ?

arr evaluates to a pointer, you said and i said, arr is a pointer. What is difference in that ?

Context. arr is an array, but when used in value context it evaluates to a pointer to the first element. Saying "arr is a pointer" implies that it's always a pointer, which is a misleading statement.

hmm.. so it's "sometimes" evaluates to a pointer but not always. yes! i got it.
hey deceptikon, can you tell one thing to me that

*y++;

this statement evaluates from right to left. right ?
so, isn't firstly p++ should be incremented ? because (p++) firstly(if we travel from right to left) and then using that value using "*" operator. I know i am wrong. But I am not getting how i am wrong ?

secondly, in the expression, only y is incremented ? right ? so what is the use of * over there because i am not assiging it's value or using it value in this only expression. please make me correct. thanks .

this statement evaluates from right to left. right ?
so, isn't firstly p++ should be incremented ? because (p++) firstly(if we travel from right to left) and then using that value using "*" operator. I know i am wrong. But I am not getting how i am wrong ?

Excellent question! Nice eye for detail. :) The increment operator does indeed evaluate from right to left, but remember how the post increment operator works: it increments the object's value but evaluates to the value before the increment. So this:

int var = 0;

printf("%d\n", var++);
printf("%d\n", var);

Is functionally equiavalent to this:

int var = 0;
int temp = var;

var = var + 1;

printf("%d\n", temp);
printf("%d\n", var);

secondly, in the expression, only y is incremented ? right ? so what is the use of * over there because i am not assiging it's value or using it value in this only expression.

There's no purpose for dereferencing the pointer because you're not doing anything with the result. If all you're doing in the statement is incrementing y then I'd suggest this instead:

++y;

The pre increment operator is conceptually more efficient because it doesn't need to use a temporary variable. In practice there's really no difference because removing that temporary variable if it's not needed was one of the first optimizations in one of the first C compilers. I'd be shocked if any compiler didn't apply that optimization even with optimizations disabled.

hey, it's an good question which comes up! which temporaray variable you are talking about ? amazon has asked question in interview "++i" is fast or i=i+1 ? please tell this thing. how temporary variable concept is involved ?
thanks.

which temporaray variable you are talking about ?

It's implicit and imaginary. The temporary variable is used to describe the functionality of saving the current value, incrementing the value, then returning the saved value.

amazon has asked question in interview "++i" is fast or i=i+1 ? please tell this thing.

It really depends on what you're allowed to assume from the question. If you're assuming that this is C, and both expressions are their own statement, and optimizations are turned on, both will be equally fast because the ultimate machine code is pretty much guaranteed to be identical.

If it's C++ then operator overloading throws a wrench into your assumptions. If the expressions are part of a larger expression then there are a potentially significant number of differences that could affect performance. Finally, on the off chance that you're using an incredibly naive compiler, turning optimizations off could produce less efficient machine code for i = i + 1 if the instruction set of the processor supports an in-place increment instruction and if ++i uses that instruction.

So my expectation when interviewing with this question would be for the candidate to reply with further questions to establish context.

So, if this is the matter, I must ask about shorthand operators. So, As per explaination,

f=f+10;

And,

f+=10;

Are they both equally fast ?
right ? (if optimizations are on and these days compilers are used)

oops! till today, I was using shorthand operators thinking that they are fast as compared to other statements. I was wrong. U have said "yes". That means they are "equally" fast. right ? Am i understanding right ?

I'm not sure how "yes" could have been misinterpreted for that question. Yes, they are equally fast, assuming optimizations are enabled on a modern compiler.

This question has already been answered. Start a new discussion instead.