Alternate pgm for the given pgm without using function - c

#include <stdio.h>
void lower_string(char*);
int main()
{
char string[100];
printf("Enter a string to convert it into lower case\n");
gets(string);
lower_string(string);
printf("Entered string in lower case is \"%s\"\n", string);
return 0;
}
void lower_string(char *string)
{
while(*string)
{
if ( *string >= 'A' && *string <= 'Z' )
{
*string = *string + 32;
}
string++;
}
}
In this program what if i replace *string with string[]?
can anyone help me in writing the above program without using any function?
And please explain what does this mean while(*str) ?

void lower_string(char *string);
and
void lower_string(char string[]);
are equivalent in C. A parameter of type char [] is adjusted to type char *.
Of course when string is the operand of the * operator like in:
while (*string)
then you cannot change it to string[] as * here is the indirection operator and not a part of a type name.

There is no difference between the two, because when an array is passed to a function, it decays adjusts to a pointer.
I wouldn't write such code and then tag it C++, because string is a standard library class name.

C-FAQ: Q-6.4:
Since arrays decay immediately into pointers, an array is never actually passed to a function. You can pretend that a function receives an array as a parameter, and illustrate it by declaring the corresponding parameter as an array:
void f(char a[])
{ ... }
Interpreted literally, this declaration would have no use, so the compiler turns around and pretends that you'd written a pointer declaration, since that's what the function will in fact receive:
void f(char *a)
{ ... }
There's nothing particularly wrong with talking about a function as if it ``receives'' an array, if the function is traditionally used to operate on arrays, or if the parameter is naturally treated within the function as an array.
This conversion of array-like declarators into pointers holds only within function formal parameter declarations, nowhere else.

The symbol [] is basically equivalent to * in some way.
You can accept char[] and still treat it as a pointer with * and you can accept a char* as a parameter and access it with [] as a regular array - it's exactly the same.
You're always getting a pointer to that spot in memory, when it's an array defined with [] though, the pointer will be constant (can't deference it, only access where it's pointing to).
When you're declaring an array using char str[100]; you're actually declaring a const char* named str and pointing to a memory area in the stack.

They are pretty much the same thing. For example,
sz[x];
is short for
*(sz + x);
However, when you write char *sz;, all yau are getting is a pointer. Wen you write char sz[size];, you are getting an array also. See haccks' answer.

Related

Pointer of Strings and Integers

I would like some help with pointer of strings and integers. If I intend to change the value of integers defined in the main function, it is necessary to pass the pointer of the variables otherwise nothing will be changed like: (a and b will swap to each other's original value)
void swapping(int *a,int *b){
int temp=0;
temp= *a;
*a=*b;
*b=temp;
}
int main(){
int a=1,b=2;
swapping(&a,&b);
printf("%d\n%d\n",a,b );
return 0;
}
However, when I continue on passing strings(char arrays), operations like this is feasible:
void split(char take1[],char take2[], char str[]){
int i=0,j=0,yes=0;
while(str[i]!='\0'){
if(str[i]=='*'){
yes=1;
i++;
}
if(yes==0){
take1[i]=str[i];
}
else if (yes!=0){
take2[j]=str[i];
j++;
}
i++;
}
}
int main(){
char taker1[30],taker2[30];
char str[30]="Hello*world";
split(taker1,taker2,str);
printf("%s\n%s\n",taker1,taker2) ;
return 0;
}
My shallow understanding is because functions that get called are temporarily stored in RAM, so the value reassigned in the function will be removed once the function call is finished. Thus, we need to change the value of pointer in the memory.
But I didn't get why there is no need to pass the pointer of the char arrays as in second example to the function(split()) to alter their values . Could someone please help to see why? Thanks!
(OP) But I didn't get why there is no need to pass the pointer of the char arrays as in second example to the function(split()) to alter their values .
With many operations1, arrays are converted to the pointer of the first element. That happened with
split(taker1,taker2,str);
Let's dig deeper.
The C standard library defines string
A string is a contiguous sequence of characters terminated by and including the first null character. C17dr § 7.1.1 1
char array str below contains a string.
char str[30]="Hello*world";
char arrays taker1, taker2 are uninitialized. They do not certainly contain a string.
char taker1[30],taker2[30];
(OP) I continue on passing strings(char arrays),
Not quite. Below, char array taker1 is converted to the address of the first element when passed to the function. Like-wise for taker2, str
split(taker1, taker2, str);
split() receives 3 pointers, even though it may look like arrays.
void split(char take1[],char take2[], char str[]){
// same as
void split(char *take1, char *take2, char *str) {
The body of split() then uses these pointers to manipulate data. Recall these pointers point to main's str[], taker1[], taker2[]. When splt() is done, printf("%s\n%s\n", taker1, taker2) ; shows the effect.
1 Except when it is the operand of the sizeof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type “array of type” is converted to an expression with type “pointer to type” that points to the initial element of the array object and is not an lvalue. C17dr
char take[] is essentially the same as char *take. So you actually passing the pointer.
In char taker[30] case for example taker itself is a pointer and taker[n] is equivalent to *(taker + n).
EXPLANATION
This is because, in C, an array declaration decays to a pointer internally (Refer to the citation at the end for details). When you declare char a[], it is the same as declaring char* a. In both of these cases, a stores the memory address of the first element of the array. But, in the case of variables like plain integers or characters, such as int x = 10;, the variable x will actually store the value 10.
When you declare an array such as
char a[10];
the object designated by the expression a is an array (i.e., a contiguous block of memory large enough to hold 10 character values a.k.a string), and the type of the expression a is an "array of 10 character elements", or char[10]. The expression a is implicitly converted to char *, and its value is the address of the first element.
Thus, when you pass an array variable to a function, you are actually passing the memory address (or base address) of the array. And since you have written your function declaration as:
void split(char take1[],char take2[], char str[])
It is the same as writing:
void split(char *take1,char *take2, char *str)
And, in your function call which is:
split(taker1,taker2,str);
taker1, taker2 and str actually contain base addresses of the respective character arrays (i.e. string). So you don't explicitly have to mention the address_of operator (&) along with the array variables in the function call.
The code you have posted can also be written as follows:
void split(char *take1,char *take2, char *str){
int i=0,j=0,yes=0;
while(*(str+i) != '\0'){
if(*(str+i) == '*'){
yes=1;
i++;
}
if(yes==0){
*(take1+i) = *(str+i);
}
else if (yes!=0){
*(take2+i) = *(str+i);
j++;
}
i++;
}
}
int main(){
char taker1[30], taker2[30];
char str[30] = "Hello*world";
split(taker1, taker2, str);
printf("%s\n%s\n", taker1, taker2) ;
return 0;
}
Notice the interchanged array operator([]) and and dereference operator(*). Hint: Writing arr[5] is the same as *(arr + 5).
LONG STORY SHORT:
In C, arrays are passed by reference. Normal variables are passed by value.
Array variables can be treated as pointers.
You ought to normally skip the & with array variables in function calls.
BONUS
The aforementioned reason is also why we don't use & in scanf() for string variables (with %s format specifier), i.e.,
char str[10];
scanf("%s", str);
But in the case of integers or other primaries:
int num;
scanf("%d", &num);
Also, you will get a better understanding of the concepts involved after going through dynamic memory allocation in C.
CITATION
Here's the exact language from the C standard (n1256):
6.3.2.1 Lvalues, arrays, and function designators ... 3 Except when it is the operand of the sizeof operator or the unary & operator or is a
string literal used to initialize an array, an expression that has
type ‘‘array of type’’ is converted to an expression with type
‘‘pointer to type’’ that points to the initial element of the array
object and is not an lvalue. If the array object has register storage
class, the behavior is undefined.

C difference between *[] and **

This might be a bit of a basic question, but what is the difference between writing char * [] and char **? For example, in main,I can have a char * argv[]. Alternatively I can use char ** argv. I assume there's got to be some kind of difference between the two notations.
Under the circumstances, there's no difference at all. If you try to use an array type as a function parameter, the compiler will "adjust" that to a pointer type instead (i.e., T a[x] as a function parameter means exactly the same thing as: T *a).
Under the right circumstances (i.e., not as a function parameter), there can be a difference between using array and pointer notation though. One common one is in an extern declaration. For example, let's assume we have one file that contains something like:
char a[20];
and we want to make that visible in another file. This will work:
extern char a[];
but this will not:
extern char *a;
If we make it an array of pointers instead:
char *a[20];
...the same remains true -- declaring an extern array works fine, but declaring an extern pointer does not:
extern char *a[]; // works
extern char **a; // doesn't work
Depends on context.
As a function parameter, they mean the same thing (to the compiler), but writing it char *argv[] might help make it obvious to programmers that the char** being passed points to the first element of an array of char*.
As a variable declaration, they mean different things. One is a pointer to a pointer, the other is an array of pointers, and the array is of unspecified size. So you can do:
char * foo[] = {0, 0, 0};
And get an array of 3 null pointers. Three char*s is a completely different thing from a pointer to a char*.
You can use cdecl.org to convert them to English:
char *argv[] = declare argv as array of pointer to char
char **argv = declare argv as pointer to pointer to char
I think this is a little bit more than syntactic sugar, it also offers a way to express semantic information about the (voluntary) contract implied by each type of declaration.
With char*[] you are saying that this is intended to be used as an array.
With char**, you are saying that you CAN use this as an array but that's not the way it's intended to be used.
As it was mentioned in the other answers, char*[] declares an array of pointers to char, char** declares a pointer to a pointer to char (which can be used as array).
One difference is that the array is constant, whereas the pointer is not.
Example:
int main()
{
char** ppc = NULL;
char* apc[] = {NULL};
ppc++;
apc++; /* this won't compile*/
return 0;
}
This really depends on the context of where the declarations occur.
Outside of a function parameter definition, the declaration
T a[];
declares a as an unknown-sized array of T; the array type is incomplete, so unless a is defined elsewhere (either in this translation unit or another translation unit that gets linked) then no storage is set aside for it (and you will probably get an "undefined reference" error if you attempt to link, although I think gcc's default behavior is to define the array with 1 element) . It cannot be used as an operand to the sizeof operator. It can be used as an operand of the & operator.
For example:
/**
* module1.c
*/
extern char *a[]; /* non-defining declaration of a */
void foo()
{
size_t i = 0;
for (i = 0; a[i] != NULL; i++)
printf("a[%lu] = %s\n", (unsigned long) i, a[i++]);
}
module1.c uses a non-defining declaration of a to introduce the name so that it can be used in the function foo, but since no size is specified, no storage is set aside for it in this translation unit. Most importantly, the expression a is not a pointer type; it is an incomplete array type. It will be converted to a pointer type in the call to printf by the usual rules.
/**
* module2.c
*/
char *a[] = {"foo", "bar", "bletch", "blurga", NULL}; /* defining declaration of a */
int main(void)
{
void foo();
foo();
return 0;
}
module2.c contains a defining declaration for a (the size of the array is computed from the number of elements in the initializer), which causes storage to be allocated for the array.
Style note: please don't ever write code like this.
In the context of a function parameter declaration, T a[] is synonymous with T *a; in both cases, a is a pointer type. This is only true in the context of a function parameter declaration.
As Paul said in the comment above, it's syntactic sugar. Both char* and char[] are the same data type. In memory, they will both contain the address of a char.
The array/index notation is equivalent to the pointer notation, both in declaration and in access, but sometimes much more intuitive. If you are creating an array of char pointers, you may want to write it one way or another to clarify your intention.
Edit: didn't consider the case Jerry mentioned in the other answer. Take a look at that.
char *ptr[2]={"good","bad"}; //Array of ptr to char
char **str; //Refer ptr to ptr to char
int i;
//str = &ptr[0]; //work
str = ptr;
for(i=0;i<2;i++) printf("%s %s\n",ptr[i],str[i]);
Its o/p same. Using that we can easily understand.

C Programming - Pass-by-Reference

In the C program below, I don't understand why buf[0] = 'A' after I call foo. Isn't foo doing pass-by-value?
#include <stdio.h>
#include <stdlib.h>
void foo(char buf[])
{
buf[0] = 'A';
}
int main(int argc, char *argv[])
{
char buf[10];
buf[0] = 'B';
printf("before foo | buf[0] = %c\n", buf[0]);
foo(buf);
printf("after foo | buf[0] = %c\n", buf[0]);
system("PAUSE");
return 0;
}
output:
before foo | buf[0] = 'B'
after foo | buf[0] = 'A'
void foo(char buf[])
is the same as
void foo(char* buf)
When you call it, foo(buf), you pass a pointer by value, so a copy of the pointer is made.
The copy of the pointer points to the same object as the original pointer (or, in this case, to the initial element of the array).
C does not have pass by reference semantics in the sense that C++ has pass by reference semantics. Everything in C is passed by value. Pointers are used to get pass by reference semantics.
an array is just a fancy way to use a pointer. When you pass buf to the function, you're passing a pointer by value, but when you dereference the pointer, you're still referencing the string it points to.
Array as function parameter is equivalent to a pointer, so the declaration
void foo( char buf[] );
is the same as
void foo( char* buf );
The array argument is then decayed to the pointer to its first element.
Arrays are treated differently than other types; you cannot pass an array "by value" in C.
Online C99 standard (draft n1256), section 6.3.2.1, "Lvalues, arrays, and function designators", paragraph 3:
Except when it is the operand of the sizeof operator or the unary & operator, or is a
string literal used to initialize an array, an expression that has type ‘‘array of type’’ is
converted to an expression with type ‘‘pointer to type’’ that points to the initial element of
the array object and is not an lvalue. If the array object has register storage class, the
behavior is undefined.
In the call
foo(buf);
the array expression buf is not the operand of sizeof or &, nor is it a string literal being used to initialize an array, so it is implicitly converted ("decays") from type "10-element array of char" to "pointer to char", and the address of the first element is passed to foo. Therefore, anything you do to buf in foo() will be reflected in the buf array in main(). Because of how array subscripting is defined, you can use a subscript operator on a pointer type so it looks like you're working with an array type, but you're not.
In the context of a function parameter declaration, T a[] and T a[N] are synonymous with T *a, but this is only case where that is true.
*char buf[] actually means char ** so you are passing by pointer/reference.
That gives you that buf is a pointer, both in the main() and foo() function.
Because you are passing a pointer to buf (by value). So the content being pointed by buf is changed.
With pointers it's different; you are passing by value, but what you are passing is the value of the pointer, which is not the same as the value of the array.
So, the value of the pointer doesn't change, but you're modifying what it's pointing to.
arrays and pointers are (almost) the same thing.
int* foo = malloc(...)
foo[2] is the same as *(foo+2*sizeof(int))
anecdote: you wrote
int main(int argc, char *argv[])
it is also legal (will compile and work the same) to write
int main(int argc, char **argv)
and also
int main(int argc, char argv[][])
they are effectively the same. its slightly more complicated than that, because an array knows how many elements it has, and a pointer doesn't. but they are used the same.
in order to pass that by value, the function would need to know the size of the argument. In this case you are just passing a pointer.
You are passing by reference here. In this example, you can solve the problem by passing a single char at the index of the array desired.
If you want to preserve the contents of the original array, you could copy the string to temporary storage in the function.
edit: What would happen if you wrapped your char array in a structure and passed the struct? I believe that might work too, although I don't know what kind of overhead that might create at the compiler level.
please note one thing,
declaration
void foo(char buf[])
says, that will be using [ ] notation. Not which element of array you will use.
if you would like to point that, you want to get some specific value, then you should declare this function as
void foo(char buf[X]); //where X would be a constant.
Of course it is not possible, because it would be useless (function for operating at n-th element of array?). You don't have to write down information which element of array you want to get. Everything what you need is simple declaration:
voi foo(char value);
so...
void foo(char buf[])
is a declaration which says which notation you want to use ( [ ] - part ), and it also contains pointer to some data.
Moreover... what would you expect... you sent to function foo a name of array
foo(buf);
which is equivalent to &buf[0]. So... this is a pointer.
Arrays in C are not passed by value. They are not even legitimate function parameters. Instead, the compiler sees that you're trying to pass an array and demotes it to pointer. It does this silently because it's evil. It also likes to kick puppies.
Using arrays in function parameters is a nice way to signal to your API users that this thing should be a block of memory segmented into n-byte sized chunks, but don't expect compilers to care if you spell char *foo char foo[] or char foo[12] in function parameters. They won't.

Pointer / Array syntax (char **p, *p[n]) in C/C++

For pointers, I'm getting confused with declarations and function parameters on when to use char ** or char * or *array[n], etc. Like if a function takes a (*array[n]) parameter, do I pass it a **type?
I try using the Right-Left rule and know that p would be a pointer to a pointer to a char (char **p), and p is an array of n pointers (*p[n]), but someone said that *p[n] and **p are essentially equivalent. Is that true?
In the correct context (namely, arguments to a function), then the following declarations are equivalent:
int main(int argc, char *argv[]);
int main(int argc, char **argv);
int main(int argc, char *argv[12]); // Very aconventional!
Similar comments apply to the function definitions (which have a block enclosed in braces in place of the semi-colon).
In any other context, there are important differences between the notations. For example:
extern char *list1[];
extern char **list2;
extern char *list3[12];
The first says that somewhere there is an array of indeterminate size containing 'char *' values. The second says that somewhere - possibly here - there is a single value containing a pointer to a char pointer. The third says that somewhere - possibly here - there is an array of 12 character pointers.
However, all the three lists can be referenced in somewhat the same way - assuming that they actually have been defined and initialized.
list1[0][0] = '1';
list2[0][0] = '2';
list3[0][0] = '3';
Further, if they are passed into a function like this:
function(list1, list2, list3);
then the function can be declared as:
void function(char **list1, char **list2, char **list3);
The arrays (list1, list3) decay from the array to the pointer to the first element of the array; list2, of course, is already a pointer to a pointer.
One detail to note in a function such as:
void otherfunction(char *list[12])
{
...
}
The C compiler does not treat that declaration any differently from:
void otherfunction(char **list)
{
...
}
or
void otherfunction(char *list[])
{
...
}
In particular, it does no array bounds checking, and as far as the function is concerned, the 12 may as well be absent.
C99 introduces VLA (variable length array) types and also introduces a notation with 'static' and a size in the array bounds. You would need to read the standard to understand those fully.
Suffice to say in a function like the following the size of the array does matter, and is determined at run-time. With two-dimensional arrays in general, all the dimensions except the first need to be specified.
void vla_function(size_t m, int vla[m][m]);
Quoting from the standard (section 6.7.5.3):
void f(double (* restrict a)[5]);
void f(double a[restrict][5]);
void f(double a[restrict 3][5]);
void f(double a[restrict static 3][5]);
(Note that the last declaration also specifies that the argument corresponding to a in any call to f must be a
non-null pointer to the first of at least three arrays of 5 doubles, which the others do not.)
Reading C declarators (that's the part of the variable with the * and []) is fairly nuanced. There are some websites with tips:
http://www.antlr.org/wiki/display/CS652/How+To+Read+C+Declarations
http://www.ericgiguere.com/articles/reading-c-declarations.html
A char** is a pointer to (possible multiple) pointer(s) to (possibly multiple) char(s). For example, it might be a pointer to a string pointer, or a pointer to an array of string pointers.
A char*[] is an array of pointers to char. When you have a function that takes this as a parameter, the C compiler makes it "decay" into a char**. This only happens to the first layer... so, taking a complicated example, char*[4][] becomes char*(*)[4]. Read the links above so you can understand what the heck that means.
Or you can do a (very sensible) thing and make a bunch of typedefs. I don't do this, but until you're good at reading declarators, it's a good idea.
typedef char * stringp;
void func(stringp array[]) { ... }
static stringp FOUR_STRINGS[4] = { ... };
If n==0 then they reference the same memory. Array indexing is basically a pointer plus an offset. *(p[n]) would be the same as **(p+n). You can see for yourself how simple this is in C, because array[4] and 4[array] will give you the same thing.

Pointers, arrays and passing pointers to methods

Confused with the problem here. New to C, as made obvious by the below example:
#include <stdlib.h>
#include <stdio.h>
void pass_char_ref(unsigned char*);
int main()
{
unsigned char bar[6];
pass_char_ref(&bar);
printf("str: %s", bar);
return 0;
}
void pass_char_ref(unsigned char *foo)
{
foo = "hello";
}
To my understanding, bar is an unsigned character array with an element size of 6 set away in static storage. I simply want to pass bar by reference to pass_char_ref() and set the character array in that function, then print it back in main().
You need to copy the string into the array:
void pass_char_ref(unsigned char *foo)
{
strcpy( foo, "hello" );
}
Then when you call the function, simply use the array's name:
pass_char_ref( bar );
Also, the array is not in "static storage"; it is an automatic object, created on the stack, with a lifetime of the containing function's call.
Two things:
You don't need to pass &bar; just pass bar.
When you pass an array like this, the address of its first (0th) element is passed to the function as a pointer. So, call pass_char_ref like this:
pass_char_ref(bar);
When you call pass_char_ref like this, the array name "decays" into a pointer to the array's first element. There's more on this in this tutorial, but the short story is that you can use an array's name in expressions as a synonym for &array_name[0].
Pointers are passed by value. You have:
void pass_char_ref(unsigned char *foo)
{
foo = "hello";
}
In some other languages, arguments are passed by reference, so formal parameters are essentially aliases for the arguments. In such a language, you could assign "hello" to foo and it would change the contents of bar.
Since this is C, foo is a copy of the pointer that's passed in. So, foo = "hello"; doesn't actually affect bar; it sets the local value (foo) to point to the const string "hello".
To get something like pass by reference in C, you have to pass pointers by value, then modify what they point to. e.g.:
#include <string.h>
void pass_char_ref(unsigned char *foo)
{
strcpy(foo, "hello");
}
This will copy the string "hello" to the memory location pointed to by foo. Since you passed in the address of bar, the strcpy will write to bar.
For more info on strcpy, you can look at its man page.
In C, arrays are accessed using similar mechanics to pointers, but they're very different in how the definitions work - an array definition actually causes the space for the array to be allocated. A pointer definition will cause enough storage to be allocated to refer (or "point") to some other part of memory.
unsigned char bar[6];
creates storage for 6 unsigned characters. The C array semantics say that, when you pass an array to another function, instead of creating a copy of the array on the stack, a pointer to the first element in the array is given as the parameter to the function instead. This means that
void pass_char_ref(unsigned char *foo)
is not taking an array as an argument, but a pointer to the array. Updating the pointer value (as in foo = "hello";, which overwrites the pointer's value with the address of the compiled-in string "hello") does not affect the original array. You modify the original array by dereferencing the pointer, and overwriting the memory location it points to. This is something that the strcpy routine does internally, and this is why people are suggesting you use
void pass_char_ref(unsigned char *foo)
{
strcpy(foo, "hello");
}
instead. You could also say (for sake of exposition):
void pass_char_ref(unsigned char *foo)
{
foo[0] = 'h';
foo[1] = 'e';
foo[2] = 'l';
foo[3] = 'l';
foo[4] = 'o';
foo[5] = 0;
}
and it would behave correctly, too. (this is similar to how strcpy will behave internally.)
HTH
Please see here to an explanation of pointers and pass by reference to a question by another SO poster. Also, here is another thorough explanation of the differences between character pointers and character arrays.
Your code is incorrect as in ANSI C standard, you cannot pass an array to a function and pass it by reference - other data-types other than char are capable of doing that. Furthermore, the code is incorrect,
void pass_char_ref(unsigned char *foo)
{
foo = "hello";
}
You cannot assign a pointer in this fashion to a string literal as pointers use the lvalue and rvalue assignment semantics (left value and right value respectively). A string literal is not an rvalue hence it will fail. Incidentally, in the second link that I have given which explains the differences between pointers and arrays, I mentioned an excellent book which will explain a lot about pointers on that second link.
This code will probably make more sense in what you are trying to achieve
void pass_char_ref(unsigned char *foo)
{
strcpy(foo, "hello");
}
In your main() it would be like this
int main()
{
unsigned char bar[6];
pass_char_ref(bar);
printf("str: %s", bar);
return 0;
}
Don't forget to add another line to the top of your code #include <string.h>.
Hope this helps,
Best regards,
Tom.
Since bar[] is an array, when you write bar, then you are using a pointer to the first element of this array. So, instead of:
pass_char_ref(&bar);
you should write:
pass_char_ref(bar);
Time again for the usual spiel --
When an expression of array type appears in most contexts, its type is implicitly converted from "N-element array of T" to "pointer to T" and its value is set to point to the first element of the array. The exceptions to this rule are when the array expression is the operand of either the sizeof or & operators, or when the array is a string litereal being used as an initializer in a declaration.
So what does all that mean in the context of your code?
The type of the expression bar is "6-element array of unsigned char" (unsigned char [6]); in most cases, the type would be implicitly converted to "pointer to unsigned char" (unsigned char *). However, when you call pass_char_ref, you call it as
pass_char_ref(&bar);
The & operator prevents the implicit conversion from taking place, and the type of the expression &bar is "pointer to 6-element array of unsigned char" (unsigned char (*)[6]), which obviously doesn't match the prototype
void pass_char_ref(unsigned char *foo) {...}
In this particular case, the right answer is to ditch the & in the function call and call it as
pass_char_ref(bar);
Now for the second issue. In C, you cannot assign string values using the = operator the way you can in C++ and other languages. In C, a string is an array of char with a terminating 0, and you cannot use = to assign the contents of one array to another. You must use a library function like strcpy, which expects parameters of type char *:
void pass_char_ref(unsigned char *foo)
{
strcpy((char *)foo, "hello");
}
Here's a table of array expressions, their corresponding types, and any implicit conversions, assuming a 1-d array of type T (T a[N]):
Expression Type Implicitly converted to
---------- ---- -----------------------
a T [N] T *
&a T (*)[N]
a[0] T
&a[0] T *
Note that the expressions a, &a, and &a[0] all give the same value (the address of the first element in the array), but the types are all different.
The use of the address of operator (&) on arrays is no longer allowed. I agree that it makes more sense to do &bar rather than bar, but since arrays are ALWAYS passed by reference, the use of & is redundant, and with the advent of C++ the standards committee made it illegal.
so just resist the urge to put & before bar and you will be fine.
Edit: after a conversation with Roger, I retract the word illegal. It's legal, just not useful.

Resources