4

I'm trying to better understand the & operator (address-of) for use within an API.

Here is my example API function signature:

apiFunction(const int*)

I am working on somebody else's code and they are using the API as follows:

int inputs[1] = {1};
apiFunction((const int*)&inputs);

I would think the correct usage should be:

int inputs[1] = {1};
apiFunction(inputs);

Is there a difference between 'inputs' and '&inputs' when 'inputs' is a char array with length 1?

They looks the same when I do a printf, but I fear that I may be formatting it incorrectly:

printf("%p, %p", inputs, (const int*)&inputs);

Output (for example):

0204DE94 0204DE94
Caprooja
  • 855
  • 7
  • 11
  • 1
    Why do you need to cast `&inputs`? That should be the type you're looking for automatically. It's also the responsibility of the caller to correctly encode the arguments, so calling `&` when an address is required shouldn't come as a surprise. – tadman Aug 10 '17 at 16:47
  • https://stackoverflow.com/questions/1461432/what-is-array-decaying – stark Aug 10 '17 at 16:48
  • @tadman maybe he is compiling using C++ compiler. – 0___________ Aug 10 '17 at 16:53
  • Waht is the reason of declaring table with the length 1? – 0___________ Aug 10 '17 at 17:00
  • @PeterJ Purpose for length 1 array is not obvious because I have simplified the actual code I'm working on. API actually accepts array length and then a pointer to the array of inputs. API can handle more than 1 input, but for my application I only need 1 input. – Caprooja Aug 10 '17 at 17:04
  • @tadman Agreed. The surprise is that &inputs is the "address of the array" and not the "address of the address of the array". – Caprooja Aug 10 '17 at 17:12
  • Why would `&inputs` be the address of the address? `&` loosely translates to "address of" in C. – tadman Aug 10 '17 at 17:15
  • @tadman because inputs without the & operator is an int* (and a pointer is an address) obviously I'm wrong, but trying to explain my thought process – Caprooja Aug 10 '17 at 17:17
  • Don't confuse "can be interpreted as" with "is actually". C treats arrays and pointers as two sides of the same coin, but they're not literally the same thing. The compiler will handle the conversion for you if necessary, but some conversion is necessarily required. – tadman Aug 10 '17 at 17:18

1 Answers1

3

The expression &input has type int (*)[1], i.e. a pointer to an array of size 1. This is in contrast to input which (in most contexts) decays to a pointer to the first element and has type int *.

While the address of an array and the address of the first element are the same, the difference in the type of each one comes into play when pointer arithmetic is applied.

In the context of apiFunction which expects a const int *, you can get away with passing either &input (with a cast) or input as both have the same value. However, the latter is the proper way to do this:

apiFunction(inputs);

So you are correct that the code you found is not passing the parameter properly.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • Code is not passing parameter properly, but it is functionally OK because they have the same value. That's what I'm getting from your answer – Caprooja Aug 10 '17 at 17:07
  • Usually when something with pointers is functionally OK because they have the same value, it’s technically UB but the compiler does the obvious thing and it works out in practice. In this case I think it actually is well-defined as doing the same thing. – Daniel H Aug 10 '17 at 17:09
  • @Caprooja That is correct, it works because `input` and `&input` have the same value. – dbush Aug 10 '17 at 17:11
  • @DanielH It is the cast `(const int*)&inputs` that is weak. Converting from a `int**` to `const int*`. IIRC, the pointer to a simple type like `int` may be of different size _and representation_ (and if properly converted _equate_ to each other) than a `pointer to a pointer` and the conversion is a problem, unless it goes through `void *`. OTOH, [the speed limit is 55](https://www.reddit.com/r/NoStupidQuestions/comments/2xy8ra/why_does_noone_in_the_us_follow_the_speed_limit/) – chux - Reinstate Monica Aug 10 '17 at 18:22
  • There are no pointers to pointers; decay doesn’t happen there. `&inputs` has type `int[1]*`, or pointer to array of one `int`. I think you can convert between a pointer to an array and a pointer to its element type, at least if its elements are standard layout and probably no matter what. – Daniel H Aug 10 '17 at 19:06
  • (Oops, I wrote the type wrong; it’s really `int (*)[1]`) – Daniel H Aug 10 '17 at 19:17