[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 361
  • Last Modified:

Difference between array name and array address ?

 ParameterResult ParameterString::setValue(const char * val, unsigned short size, bool force);

const char testbuff [ ] = {0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, 0x00, 0x03, 0x00, 0x05, 0x00, 0x06, 0x00};

supportedServParam->setValue (  (const char * ) &testbuff,  sizeof ( testbuff )  ) ;

Open in new window



Shouldn't we be passing  'testbuff' instead ?  'testbuff' is address of first element of array.  What is '&testbuff' ?
0
naseeam
Asked:
naseeam
  • 4
  • 4
  • 3
3 Solutions
 
jkrCommented:
You're right, there should be no '&' - actually, that's what requires the '(const char*)' cast, which would not be necessary if only 'testbuf' was used, since '&testbuf' is actually a 'char**'.
0
 
sarabandeCommented:
the address of the array in memory is equal to the address of the first array element.

you can use this information to distinguish between pointers and arrays (what can be useful if you need to know whether sizeof function is valid to determine the size of the array). note, an array passed to a function as an argument was always turned to a pointer.

in the call above it would be better to have

supportedServParam->setValue (&testbuff[0],  sizeof (testbuff )  ) ;

Open in new window

what also spares the cast and makes clear that a pointer to char was passed rather than the whole array.

Sara
0
 
jkrCommented:
Would you mind to elaborate why '&testbuf[0]' is better than 'testbuf'? I am really curious now...
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
naseeamAuthor Commented:
From expert responses, I gather that it's correct to pass address of array as long as it is typecasted as follows:

(const char * ) &testbuff

but shouldn't it be as follows ?

(const char * *) &testbuff
0
 
jkrCommented:
No, that would cause an error, since the method takes a 'const char*' as the 1st argument. Again, if you only use 'testbuf' (as you assumed) no cast is necessary.
0
 
naseeamAuthor Commented:
Why is it correct to pass as follows ?

(const char * ) &testbuff

I believe 'testbuff' is pointer constant.  Address of constant doesn't make sense to me.
0
 
jkrCommented:
>>Address of constant doesn't make sense to me.

That's what I'm saying ;o)

Actually, I am surprised that this works at runtime. I however suspect that your compiler places the array alements atr the same address on the stack, so that it works by chance. Why don't you just try

supportedServParam->setValue (  testbuff,  sizeof ( testbuff )  ) ;

Open in new window


and see how it works?
0
 
naseeamAuthor Commented:
I tried it.  It works!
supportedServParam -> setValue ( testbuff ,  sizeof (testbuff ) ) ;

Open in new window


In both cases, argument passed from calling function and argument received from called function
is 0xA00073C0.
0
 
naseeamAuthor Commented:
Thank you for answering follow up questions and getting to the root of the problem.
0
 
sarabandeCommented:
Would you mind to elaborate why '&testbuf[0]' is better than 'testbuf'? I am really curious now...
there are a few good reasons:

one is that the function argument is declared as char pointer. hence it is good if we pass a pointer to char explicitly rather than an array variable where the compiler does the cast implicitly.

other advantage is the readability. passing the address of the first array element together with the size, makes it clear that we pass the array from begin and how many elements can be accessed by the function. we also would see that we could point to second or n-th element accordingly.

int arr[nmax] = { 0 };
f(&arr[5], nmax -5); 

Open in new window


if you pass arrays always by address of an array element (as I do if i don't use std::vector), then you always are aware that the array turns to a pointer in the called function.

finally, you could use pointers to array elements when an iterator is required:

int arr[] = { 7, 2, 1, 9, 8 };
int n = (int)sizeof(arr)/sizeof(arr[0]);
std::sort(&arr[0], &arr[n]); // sorts the array

Open in new window


when using a std::vector<int> vec for the array, the sort statement would pass vec.begin(), vec.end() which are iterators.

in the sample code you also could pass 'arr' as first argument and the compiler would not complain. but if you look at the second argument you see that it isn't actually a pointer to a valid array element but an address that points beyond the array boundaries. obviously, it is better here that we pass the first argument in the same notation, to make clear that both the arguments have same argument type.

in my opinion, this argument is valid for all cases where an array was passed to a function.

Sara
0
 
sarabandeCommented:
I believe 'testbuff' is pointer constant.  Address of constant doesn't make sense to me.
the const of the first argument has no meaning for the caller but only for the called function (callee). the callee cannot write to the memory the pointer is pointing to when the pointer is declared to be const.

for the cast in the caller, the const has no meaning. it also would work when you omit the const. the cast was casting the address of a char array (&testbuff), what is a pointer to char array, what is equivalent to pointer to char pointer, to a char pointer. generally, pointers can be casted to any other pointer type if you use a reinterpret_cast, what means that the types of the pointers are ignored.

sometype * p1;
anothertype * p2;
p2 = reinterpret_cast<sometype *>(p1);

Open in new window


if 'anothertype' is a pointer type, you have a similar situation as in your code sample. in c++ you also can use c cast where the compiler decides which variant of static_cast, const_cast, dynamic_cast, or reinterpret_cast was used.

sometype * p1;
anothertype * p2;
p2 = (sometype *)(p1);

Open in new window



for pointer casts a c cast is always a reinterpret_cast as long as the pointers are not pointing to class types or functions where the class relation or argument list was considered. so the c cast in your code sample only tells the compiler that it should use the address of the array variable testbuff as a 'const char *'. as this was the required argument type, the compiler neither complains nor does it fail cause the addresses are equal as you have seen in the debugger.

Sara
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 4
  • 4
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now