0

I have many functions like:

void write(char* param, int len)
{
    //
}

And I notice that I almost never use the & operator for arguments. When I pass an array:

char in[20];
write(in, 20);

I dont need it, but when I pass a single value:

write(5, 1);

I don't seem to need it, and when I pass a pointer:

char* in = malloc(20);
write(in, 20);

I also dont need it. So in which circumstances do I actually need to call:

write(&in, 1);

Because I'm confused :D

Maestro
  • 9,046
  • 15
  • 83
  • 116

5 Answers5

4

Are you sure about your second case? It doesn't compile for me and should be

char in = 5;
write(&in, 1);
simonc
  • 41,632
  • 12
  • 85
  • 103
  • Im using GCC and it compiles without warning for me? But I'm using write(5, 1), instead of using an intermediate variabele like the example. So maybe it compiles because it thinks 5 is a pointer? – Maestro Jan 30 '13 at 17:41
  • GCC v4.6.2 on x86 gives a "pointer from integer without cast" warning for me. This happens for the code in your question and in your comment. You could try enabling warnings - add `-Wall` to your compiler command - to see if that helps you see the warning. – simonc Jan 30 '13 at 17:46
  • I had -Wall already enabled. The only difference is that its not for x86 but for ARM. – Maestro Jan 30 '13 at 17:49
  • I found the reason. I was calling write(0, 1). When I change it to write(5, 1) I get the warning. I think it threats 0 as a NULL-pointer. – Maestro Jan 30 '13 at 17:53
2

When are values implicitly converted to pointers?

In practice, integer types may be converted to pointers implicitly by the compiler. In theory, this is illegal and compilers that accept it will usually issue a warning:

example.c:2:6: warning: incompatible integer to pointer conversion initializing
               'void *' with an expression of type 'int'

In your above example:

char in = 5;
write(in, 20);

char is an integer type, so if your compiler allows it, it may be implicitly converted to a pointer type, although it is not part of the C standard and is completely compiler-specific.

Note that converting an integer type to a pointer type using a cast is allowed by the standard, although results are implementation-defined:

char in = 5;
write((char *)in, 20);

The only allowed case of implicit conversion is when integer constant 0, which denotes a null pointer:

write(0, 20);    // allowed

Note that the integer constant is itself allowed, but a variable of integer type with the value 0 is not:

char in = 0;
write(in, 20);   // not allowed

As for the others, when you pass a pointer, you don't need the &, obviously, because it's already a pointer. When you pass an array, it decays to a pointer so you don't need & there either. In both these cases it would be actually illegal to use it, as your function above expects a char * and be fed with a char ** and a char (*)[20] respectively.

Community
  • 1
  • 1
netcoder
  • 66,435
  • 19
  • 125
  • 142
  • ... except as required by the standard: There is a guaranteed conversion between 0 and a null pointer of any pointer type, and back again. – autistic Jan 30 '13 at 17:58
1

If you copy somehow the prototype of function 'write' to the file where you call this function, as follows.

void write(char *in, int len);

void foo(int bar){
   char in=5;
   write(in, 1);
}

You will probably get a warning. Because in is not a pointer, though 5 can be an address. I guess if your program is compiled and linked successfully, it will crash at run-time.

Amit Yaron
  • 574
  • 1
  • 5
  • 6
1

with using; return_type function_name(prim_data_type* param...) param is a pointer that pointing an address in the memory and *param is the value in that address. Answer is about what you want to do with this param.

char in[20];

by saying that "in" is the first element's address. So at the function call:

write(in, 20);

you are sending the first element's address so in the function implementation, you can access the first element by *param, second element with *(param+1) or param[1] etc. The place that you are confused is here:

char in = 5;
write(in, 1);

Because in is the address 5 (00000005), so in the implementation of the function you are accessing that place whichever value is there. You must be careful with using like this.

In the malloc operation:

char* in = malloc(20);
write(in, 20);

in is a pointer to an address (first element's address) holding up 20 elements of char can be take space. In the function you can access to all elements with param pointer(*param is the first element, *(param+7) or param[7] is the 8. element)

In the conclusion, when you want to play with an primary data typed variable (int, float, char..) in another function, you must use;

write(&in);

By doing that, in the implementation of that write function, you can access that variable, change the value by *param with no confusion.

Note:Some explanations were simplified here for better understanding. Extra warnings would be welcomed here.

Fredrick Gauss
  • 5,126
  • 1
  • 28
  • 44
0

Functions and arrays decay into pointers in some contexts. Functions can decay into pointers to functions, and arrays can decay into a pointer to the first element of the array. No other types behave this way.

This example:

char in = 5; 
write(in, 1);

Is wrong though. You definitely need the & in that case. Are you sure it worked like that?

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
  • That's probably wrong, too. And shouldn't compile without a warning. Conversations from integer to pointer types require an explicit cast. – Carl Norum Jan 30 '13 at 17:42
  • I dont get any warnings from GCC – Maestro Jan 30 '13 at 17:46
  • 1
    As you mentioned in other comments, you were. You should be sure to tell us here exactly what you're doing, not *almost* what you're doing. – Carl Norum Jan 30 '13 at 18:15