Related
I know the following is an example of pass by reference in C++, input is passed as a reference:
void add(int &input){
++input;
}
I also know pass by reference is not available in C. My question is, does the above syntax mean something else in C (i.e pass by value or something), or is it meaningless?
Trying to compile it in C gives this error:
error: parameter name omitted
does the above syntax mean something else in C?
No, it does not. It's not valid C at all.
The & operator means two things in C. The binary one is bitwise "and", and the unary is "address of". You cannot use it in declarations.
C++ chose this for reference variable for two reasons. The first is that since it is not valid C, it will not collide with existing C code. When C++ came, they focused pretty hard on making C++ backwards compatible with C. In later versions of C++, the backwards compability with C is not a very high priority. To a large degree, this is because C++ was a fork of a pretty early version of C, and since then both languages have evolved somewhat independently. For instance C99 added (but it was removed later) variable length arrays, which were never added to C++. Another example is designated initializers.
The other reason is that the meaning of the operator is pretty similar. You can interpret it as "instead of forcing the caller to send the address, I will take the address of whatever he is sending". They simply just moved the & to the function prototype instead of the function call.
And yes, there are a few other differences between pointers and references too
A reference must be initialized. (Assigned upon declaration)
A reference cannot be reassigned to "point" to another object.
A reference must always "point" at an object. It cannot be NULL.
There is one danger with references. In C, you can be certain that a function will never change the variables you send as arguments to a function unless you're sending the address to them. This C code:
int main(void)
{
int a = 42;
foo(a);
printf("%d\n", a);
}
will ALWAYS print "42", no matter how the function foo is defined. Provided that the code compiles and there's no weird undefined behavior. In C++, you don't have that guarantee.
No, it is simply invalid syntax in C.
That is actually one of the reasons that C++ picked this syntax for the feature: it wouldn't change the meaning of any existing C code.
While C does not have pass by reference (and the code will produce compile error), you can get something closer by following the rules:
In the prototype, replace & with * const (reference cannot be reassigned).
In the body, replace reference to varname with (*varname)
When calling the method, replace arg with &(arg).
void add (int *const in)
{
++(*in) ; // increment
(*in) = 5 ; // assign
int x = *in ; // Copy value
}
does the above syntax mean something else in C (i.e pass by value or something), or it's meaningless?
It is meaningless. The program is syntactically ill-formed .
I just saw a picture today and think I'd appreciate explanations. So here is the picture:
Transcription: "C isn't that hard: void (*(*f[])())() defines f as an array of unspecified size, of pointers to functions that return pointers to functions that return void."
I found this confusing and wondered if such code is ever practical. I googled the picture and found another picture in this reddit entry, and here is that picture:
Transcription: "So the symbols can be read: f [] * () * () void. f is an array of pointers that take no argument and return a pointer that takes no argument and returns void".
So this "reading spirally" is something valid? Is this how C compilers parse?
It'd be great if there are simpler explanations for this weird code.
Apart from all, can this kind of code be useful? If so, where and when?
There is a question about "spiral rule", but I'm not just asking about how it's applied or how expressions are read with that rule. I'm questioning usage of such expressions and spiral rule's validity as well. Regarding these, some nice answers are already posted.
There is a rule called the "Clockwise/Spiral Rule" to help find the meaning of a complex declaration.
From c-faq:
There are three simple steps to follow:
Starting with the unknown element, move in a spiral/clockwise direction; when ecountering the following elements replace them with the corresponding english statements:
[X] or []
=> Array X size of... or Array undefined size of...
(type1, type2)
=> function passing type1 and type2 returning...
*
=> pointer(s) to...
Keep doing this in a spiral/clockwise direction until all tokens have been covered.
Always resolve anything in parenthesis first!
You can check the link above for examples.
Also note that to help you there is also a website called:
http://www.cdecl.org
You can enter a C declaration and it will give its english meaning. For
void (*(*f[])())()
it outputs:
declare f as array of pointer to function returning pointer to function returning void
EDIT:
As pointed out in the comments by Random832, the spiral rule does not address array of arrays and will lead to a wrong result in (most of) those declarations. For example for int **x[1][2]; the spiral rule ignores the fact that [] has higher precedence over *.
When in front of array of arrays, one can first add explicit parentheses before applying the spiral rule. For example: int **x[1][2]; is the same as int **(x[1][2]); (also valid C) due to precedence and the spiral rule then correctly reads it as "x is an array 1 of array 2 of pointer to pointer to int" which is the correct english declaration.
Note that this issue has also been covered in this answer by James Kanze (pointed out by haccks in the comments).
The "spiral" rule kind of falls out of the following precedence rules:
T *a[] -- a is an array of pointer to T
T (*a)[] -- a is a pointer to an array of T
T *f() -- f is a function returning a pointer to T
T (*f)() -- f is a pointer to a function returning T
The subscript [] and function call () operators have higher precedence than unary *, so *f() is parsed as *(f()) and *a[] is parsed as *(a[]).
So if you want a pointer to an array or a pointer to a function, then you need to explicitly group the * with the identifier, as in (*a)[] or (*f)().
Then you realize that a and f can be more complicated expressions than just identifiers; in T (*a)[N], a could be a simple identifier, or it could be a function call like (*f())[N] (a -> f()), or it could be an array like (*p[M])[N], (a -> p[M]), or it could be an array of pointers to functions like (*(*p[M])())[N] (a -> (*p[M])()), etc.
It would be nice if the indirection operator * was postfix instead of unary, which would make declarations somewhat easier to read from left to right (void f[]*()*(); definitely flows better than void (*(*f[])())()), but it's not.
When you come across a hairy declaration like that, start by finding the leftmost identifier and apply the precedence rules above, recursively applying them to any function parameters:
f -- f
f[] -- is an array
*f[] -- of pointers ([] has higher precedence than *)
(*f[])() -- to functions
*(*f[])() -- returning pointers
(*(*f[])())() -- to functions
void (*(*f[])())(); -- returning void
The signal function in the standard library is probably the type specimen for this kind of insanity:
signal -- signal
signal( ) -- is a function with parameters
signal( sig, ) -- sig
signal(int sig, ) -- which is an int and
signal(int sig, func ) -- func
signal(int sig, *func ) -- which is a pointer
signal(int sig, (*func)(int)) -- to a function taking an int
signal(int sig, void (*func)(int)) -- returning void
*signal(int sig, void (*func)(int)) -- returning a pointer
(*signal(int sig, void (*func)(int)))(int) -- to a function taking an int
void (*signal(int sig, void (*func)(int)))(int); -- and returning void
At this point most people say "use typedefs", which is certainly an option:
typedef void outerfunc(void);
typedef outerfunc *innerfunc(void);
innerfunc *f[N];
But...
How would you use f in an expression? You know it's an array of pointers, but how do you use it to execute the correct function? You have to go over the typedefs and puzzle out the correct syntax. By contrast, the "naked" version is pretty eyestabby, but it tells you exactly how to use f in an expression (namely, (*(*f[i])())();, assuming neither function takes arguments).
In C, declaration mirrors usage—that’s how it’s defined in the standard. The declaration:
void (*(*f[])())()
Is an assertion that the expression (*(*f[i])())() produces a result of type void. Which means:
f must be an array, since you can index it:
f[i]
The elements of f must be pointers, since you can dereference them:
*f[i]
Those pointers must be pointers to functions taking no arguments, since you can call them:
(*f[i])()
The results of those functions must also be pointers, since you can dereference them:
*(*f[i])()
Those pointers must also be pointers to functions taking no arguments, since you can call them:
(*(*f[i])())()
Those function pointers must return void
The “spiral rule” is just a mnemonic that provides a different way of understanding the same thing.
So this "reading spirally" is something valid?
Applying spiral rule or using cdecl are not valid always. Both fails in some cases. Spiral rule works for many cases, but it is not universal.
To decipher complex declarations remember these two simple rules:
Always read declarations from inside out: Start from innermost, if any, parenthesis. Locate the identifier that's being declared, and start deciphering the declaration from there.
When there is a choice, always favour [] and () over *: If * precedes the identifier and [] follows it, the identifier represents an array, not a pointer. Likewise, if * precedes the identifier and () follows it, the identifier represents a function, not a pointer. (Parentheses can always be used to override the normal priority of [] and () over *.)
This rule actually involves zigzagging from one side of the identifier to the other.
Now deciphering a simple declaration
int *a[10];
Applying rule:
int *a[10]; "a is"
^
int *a[10]; "a is an array"
^^^^
int *a[10]; "a is an array of pointers"
^
int *a[10]; "a is an array of pointers to `int`".
^^^
Let's decipher the complex declaration like
void ( *(*f[]) () ) ();
by applying the above rules:
void ( *(*f[]) () ) (); "f is"
^
void ( *(*f[]) () ) (); "f is an array"
^^
void ( *(*f[]) () ) (); "f is an array of pointers"
^
void ( *(*f[]) () ) (); "f is an array of pointers to function"
^^
void ( *(*f[]) () ) (); "f is an array of pointers to function returning pointer"
^
void ( *(*f[]) () ) (); "f is an array of pointers to function returning pointer to function"
^^
void ( *(*f[]) () ) (); "f is an array of pointers to function returning pointer to function returning `void`"
^^^^
Here is a GIF demonstrating how you go (click on image for larger view):
The rules mentioned here is taken from the book C Programming A Modern Approach by K.N KING.
It's only a "spiral" because there happens to be, in this declaration, only one operator on each side within each level of parentheses. Claiming that you proceed "in a spiral" generally would suggest you alternate between arrays and pointers in the declaration int ***foo[][][] when in reality all of the array levels come before any of the pointer levels.
I doubt constructions like this can have any use in real life. I even detest them as interview questions for the regular developers (likely OK for compiler writers). typedefs should be used instead.
As a random trivia factoid, you might find it amusing to know that there's an actual word in English to describe how C declarations are read: Boustrophedonically, that is, alternating right-to-left with left-to-right.
Reference: Van der Linden, 1994 - Page 76
Regarding the usefulness of this, when working with shellcode you see this construct a lot:
int (*ret)() = (int(*)())code;
ret();
While not quite as syntactically complicated, this particular pattern comes up a lot.
More complete example in this SO question.
So while the usefulness to the extent in the original picture is questionable (I would suggest that any production code should be drastically simplified), there are some syntactical constructs that do come up quite a bit.
The declaration
void (*(*f[])())()
is just an obscure way of saying
Function f[]
with
typedef void (*ResultFunction)();
typedef ResultFunction (*Function)();
In practice, more descriptive names will be needed instead of ResultFunction and Function. If possible I would also specify the parameter lists as void.
I happen to be the original author of the spiral rule that I wrote oh so many years ago (when I had a lot of hair :) and was honored when it was added to the cfaq.
I wrote the spiral rule as a way to make it easier for my students and colleagues to read the C declarations "in their head"; i.e., without having to use software tools like cdecl.org, etc. It was never my intent to declare that the spiral rule be the canonical way to parse C expressions. I am though, delighted to see that the rule has helped literally thousands of C programming students and practitioners over the years!
For the record,
It has been "correctly" identified numerous times on many sites, including by Linus Torvalds (someone whom I respect immensely), that there are situations where my spiral rule "breaks down". The most common being:
char *ar[10][10];
As pointed out by others in this thread, the rule could be updated to say that when you encounter arrays, simply consume all the indexes as if written like:
char *(ar[10][10]);
Now, following the spiral rule, I would get:
"ar is a 10x10 two-dimensional array of pointers to char"
I hope the spiral rule carries on its usefulness in learning C!
P.S.:
I love the "C isn't hard" image :)
I found method described by Bruce Eckel to be helpful and easy to follow:
Defining a function pointer
To define a pointer to a function that has no arguments and no return
value, you say:
void (*funcPtr)();
When you are looking at a complex definition like
this, the best way to attack it is to start in the middle and work
your way out. “Starting in the middle” means starting at the variable
name, which is funcPtr. “Working your way out” means looking to the
right for the nearest item (nothing in this case; the right
parenthesis stops you short), then looking to the left (a pointer
denoted by the asterisk), then looking to the right (an empty argument
list indicating a function that takes no arguments), then looking to
the left (void, which indicates the function has no return value).
This right-left-right motion works with most declarations.
To review, “start in the middle” (“funcPtr is a ...”), go to the right
(nothing there – you're stopped by the right parenthesis), go to the
left and find the ‘*’ (“... pointer to a ...”), go to the right and
find the empty argument list (“... function that takes no arguments
... ”), go to the left and find the void (“funcPtr is a pointer to a
function that takes no arguments and returns void”).
You may wonder why *funcPtr requires parentheses. If you didn't use
them, the compiler would see:
void *funcPtr();
You would be declaring a function (that returns a
void*) rather than defining a variable. You can think of the compiler
as going through the same process you do when it figures out what a
declaration or definition is supposed to be. It needs those
parentheses to “bump up against” so it goes back to the left and finds
the ‘*’, instead of continuing to the right and finding the empty
argument list.
Complicated declarations & definitions
As an aside, once you figure out how the C and C++ declaration syntax
works you can create much more complicated items. For instance:
//: C03:ComplicatedDefinitions.cpp
/* 1. */ void * (*(*fp1)(int))[10];
/* 2. */ float (*(*fp2)(int,int,float))(int);
/* 3. */ typedef double (*(*(*fp3)())[10])();
fp3 a;
/* 4. */ int (*(*f4())[10])();
int main() {} ///:~
Walk through each one and use the right-left
guideline to figure it out. Number 1 says “fp1 is a pointer to a
function that takes an integer argument and returns a pointer to an
array of 10 void pointers.”
Number 2 says “fp2 is a pointer to a function that takes three
arguments (int, int, and float) and returns a pointer to a function
that takes an integer argument and returns a float.”
If you are creating a lot of complicated definitions, you might want
to use a typedef. Number 3 shows how a typedef saves typing the
complicated description every time. It says “An fp3 is a pointer to a
function that takes no arguments and returns a pointer to an array of
10 pointers to functions that take no arguments and return doubles.”
Then it says “a is one of these fp3 types.” typedef is generally
useful for building complicated descriptions from simple ones.
Number 4 is a function declaration instead of a variable definition.
It says “f4 is a function that returns a pointer to an array of 10
pointers to functions that return integers.”
You will rarely if ever need such complicated declarations and
definitions as these. However, if you go through the exercise of
figuring them out you will not even be mildly disturbed with the
slightly complicated ones you may encounter in real life.
Taken from: Thinking in C++ Volume 1, second edition, chapter 3, section "Function Addresses" by Bruce Eckel.
Remember these rules for C declares
And precedence never will be in doubt:
Start with the suffix, proceed with the prefix,
And read both sets from the inside, out.
-- me, mid-1980's
Except as modified by parentheses, of course. And note that the syntax for declaring these exactly mirrors the syntax for using that variable to get an instance of the base class.
Seriously, this isn't hard to learn to do at a glance; you just have to be willing to spend some time practising the skill. If you're going to maintain or adapt C code written by other people, it's definitely worth investing that time. It's also a fun party trick for freaking out other programmers who haven't learned it.
For your own code: as always, the fact that something can be written as a one-liner does't mean it should be, unless it is an extremely common pattern that has become a standard idiom (such as the string-copy loop). You, and those who follow you, will be much happier if you build complex types out of layered typedefs and step-by-step dereferences rather than relying on your ability to generate and parse these "at one swell foop." Performance will be just as good, and code readability and maintainability will be tremendously better.
It could be worse, you know. There was a legal PL/I statement that started with something like:
if if if = then then then = else else else = if then ...
void (*(*f[]) ()) ()
Resolving void >>
(*(*f[]) ()) () = void
Resoiving () >>
(*(*f[]) ()) = function returning (void)
Resolving * >>
(*f[]) () = pointer to (function returning (void) )
Resolving () >>
(*f[]) = function returning (pointer to (function returning (void) ))
Resolving * >>
f[] = pointer to (function returning (pointer to (function returning
(void) )))
Resolving [ ] >>
f = array of (pointer to (function returning (pointer to (function
returning (void) ))))
In my University's C programming class, the professor and subsequent book written by her uses the term call or pass by reference when referring to pointers in C.
An example of what is considered a 'call by reference function' by my professor:
int sum(int *a, int *b);
An example of what is considered a 'call by value function' by my professor:
int sum(int a, int b);
I've read C doesn't support call by reference. To my understanding, pointers pass by value.
Basically, is it incorrect to say pointers are C's way of passing by reference? Would it be more correct to say you cannot pass by reference in C but can use pointers as an alternative?
Update 11/11/15
From the way my question originated, I believe a debate of terminology has stemmed and in fact I'm seeing two specific distinctions.
pass-by-reference (the term used mainly today): The specific term as used in languages like C++
pass-by-reference (the term used by my professor as a paradigm to explain pointers): The general term used before languages like C++ were developed and thus before the term was rewritten
After reading #Haris' updated answer it makes sense why this isn't so black and white.
you cannot pass by reference in C but can use pointers as an alternative
Yup, thats correct.
To elaborate a little more. Whatever you pass as an argument to c functions, it is passed by values only. Whether it be a variable's value or the variable address.
What makes the difference is what you are sending.
When we pass-by-value we are passing the value of the variable to a function. When we pass-by-reference we are passing an alias of the variable to a function. C can pass a pointer into a function but that is still pass-by-value. It is copying the value of the pointer, the address, into the function.
If you are sending the value of a variable, then only the value will be received by the function, and changing that won't effect the original value.
If you are sending the address of a variable, then also only the value(the address in this case) is sent, but since you have the address of a variable it can be used to change the original value.
As an example, we can see some C++ code to understand the real difference between call-by-value and call-by-reference. Taken from this website.
// Program to sort two numbers using call by reference.
// Smallest number is output first.
#include <iostream>
using namespace std;
// Function prototype for call by reference
void swap(float &x, float &y);
int main()
{
float a, b;
cout << "Enter 2 numbers: " << endl;
cin >> a >> b;
if(a>b)
swap(a,b); // This looks just like a call-by-value, but in fact
// it's a call by reference (because of the "&" in the
// function prototype
// Variable a contains value of smallest number
cout << "Sorted numbers: ";
cout << a << " " << b << endl;
return 0;
}
// A function definition for call by reference
// The variables x and y will have their values changed.
void swap(float &x, float &y)
// Swaps x and y data of calling function
{
float temp;
temp = x;
x = y;
y = temp;
}
In this C++ example, reference variable(which is not present in C) is being used. To quote this website,
"A reference is an alias, or an alternate name to an existing variable...",
and
"The main use of references is acting as function formal parameters to support pass-by-reference..."
This is different then the use of pointers as function parameters because,
"A pointer variable (or pointer in short) is basically the same as the other variables, which can store a piece of data. Unlike normal variable which stores a value (such as an int, a double, a char), a pointer stores a memory address."
So, essentially when one is sending address and receiving through pointers, one is sending the value only, but when one is sending/receiving a reference variable, one is sending an alias, or a reference.
**UPDATE : 11 November, 2015**
There has been a long debate in the C Chatroom, and after reading comments and answers to this question, i have realized that there can be another way to look at this question, another perspective that is.
Lets look at some simple C code
int i;
int *p = &i;
*p = 123;
In this scenario, one can use the terminology that, p's value is a reference to i. So, if that is the case, then if we send the same pointer (int* p) to a function, one can argue that, since i's reference is sent to the function, and thus this can be called pass-by-reference.
So, its a matter of terminology and way of looking at the scenario.
I would not completely disagree with that argument. But for a person who completely follows the book and rules, this would be wrong.
NOTE: Update inspired by this chat.
Reference is an overloaded term here; in general, a reference is simply a way to refer to something. A pointer refers to the object pointed to, and passing (by value) a pointer to an object is the standard way to pass by reference in C.
C++ introduced reference types as a better way to express references, and introduces an ambiguity into technical English, since we may now use the term "pass by reference" to refer to using reference types to pass an object by reference.
In a C++ context, the former use is, IMO, deprecated. However, I believe the former use is common in other contexts (e.g. pure C) where there is no ambiguity.
Does C even have ``pass by reference''?
Not really.
Strictly speaking, C always uses pass by value. You can simulate pass by reference yourself, by defining functions which accept pointers and then using the & operator when calling, and the compiler will essentially simulate it for you when you pass an array to a function (by passing a pointer instead, see question 6.4 et al.).
Another way of looking at it is that if an parameter has type, say, int * then an integer is being passed by reference and a pointer to an integer is being passed by value.
Fundamentally, C has nothing truly equivalent to formal pass by reference or c++ reference parameters.
To demonstrate that pointers are passed by value, let's consider an example of number swapping using pointers.
int main(void)
{
int num1 = 5;
int num2 = 10;
int *pnum1 = &num1;
int *pnum2 = &num2;
int ptemp;
printf("Before swap, *Pnum1 = %d and *pnum2 = %d\n", *pnum1, *pnum2);
temp = pnum1;
pnum1 = pnum2;
pnum2 = ptemp;
printf("After swap, *Pnum1 = %d and *pnum2 = %d\n", *pnum1, *pnum2);
}
Instead of swapping numbers pointers are swapped. Now make a function for the same
void swap(int *pnum1, int *pnum2)
{
int *ptemp = pnum1;
pnum1 = pnum2;
pnum2 = temp;
}
int main(void)
{
int num1 = 5;
int num2 = 10;
int *pnum1 = &num1;
int *pnum2 = &num2;
printf("Before swap, *pnum1 = %d and *pnum2 = %d\n", *pnum1, *pnum2);
swap(pnum1, pnum2);
printf("After swap, *pnum1 = %d and *pnum2 = %d\n", *pnum1, *pnum2);
}
Boom! No swapping!
Some tutorials mention pointer reference as call by reference which is misleading. See the this answer for the difference between passing by reference and passing by value.
From the C99 standard (emphasis mine):
6.2.5 Types
20 Any number of derived types can be constructed from the object and function types, as
follows:
...
— A pointer type may be derived from a function type or an object type, called the referenced type. A pointer type describes an object whose value provides a reference to an entity of the referenced type. A pointer type derived from the referenced type T is sometimes called ‘‘pointer to T’’. The construction of a pointer type from a referenced type is called ‘‘pointer type derivation’’. A pointer type is a complete object type.
Based on the above, what your professor said makes sense and is correct.
A pointer is passed by value to functions. If the pointer points to a valid entity, its value provides a reference to an entity.
"Passing by reference" is a concept. Yes, you are passing the value of a pointer to the function, but in that instance the value of that pointer is being used to reference the variable.
Someone else used a screwdriver analogy to explain that it is wrong to refer to the passing of pointers as passing by reference, saying that you can screw a screw with a coin but that that doesn't mean you would call the coin a screw driver. I would say that is a great analogy, but they come to the wrong conclusion. In fact, while you wouldn't claim a coin was a screwdriver, you would still say that you screwed the screw in with it. i.e. even though pointers are not the same as c++ references, what you are using them to do IS passing by reference.
C passes arguments by value, period. However, pointers are a mechanism that can be used for effectively passing arguments by reference. Just like a coin can be used effectively as a screw driver if you got the right kind of screw: some screws slit are even chosen to operate well with coins. They still don't turn the coins into actual screw drivers.
C++ still passes arguments by value. C++ references are quite more limited than pointers (though having more implicit conversions) and cannot become part of data structures, and their use looks a lot more like the usual call-by-reference code would look, but their semantics, while very much catered to match the needs of call-by-reference parameters, are still more tangible than that of pure call-by-reference implementations like Fortran parameters or Pascal var parameters and you can use references perfectly well outside of function call contexts.
Your professor is right.
By value , it is copied.
By reference, it is not copied, the reference says where it is.
By value , you pass an int to a function , it is copied , changes to the copy does not affect the original.
By reference , pass same int as pointer , it is not copied , you are modifying the original.
By reference , an array is always by reference , you could have one billion items in your array , it is faster to just say where it is , you are modifying the original.
In languages which support pass-by-reference, there exists a means by which a function can be given something that can be used to identify a variable know to the caller until the called function returns, but which can only be stored in places that won't exist after that. Consequently, the caller can know that anything that will be done with a variable as a result of passing some function a reference to it will have been done by the time the function returns.
Compare the C and C# programs:
// C // C#
int x=0; int x=0;
foo(&x); foo(ref x);
x++; x++;
bar(); bar();
x++; x++;
boz(x); boz(x);
The C compiler has no way of knowing whether "bar" might change x, because
foo() received an unrestricted pointer to it. By contrast, the C# compiler
knows that bar() can't possibly change x, since foo() only receives a
temporary reference (called a "byref" in .NET terminology) to it and there
is no way for any copy of that byref to survive past the point where foo()
returns.
Passing pointers to things allows code to do the same things that can be done with pass-by-ref semantics, but pass-by-ref semantics make it possible for code to offer stronger guarantees about things it won't do.
In ISO C99, arrays that are not lvalues still decay to pointers, and may be subscripted, although they may not be modified or used after the next sequence point. (source)
I understand that this feature allows array indexing in cases where a function returning a structure containing an array, which is not allowed in C89 ( http://yarchive.net/comp/struct_return.html)
will you please help me understand why there is a restriction on using/modifying it after the next sequence point?
Note, the text OP quoted is from GCC documentation. Relevant text from C99 to back up that quote is:
C99 6.5.2.2/5
If an attempt is made to modify the result of a function call or to access it after the next
sequence point, the behavior is undefined.
and also from the list of changes in the Foreword:
conversion of array to pointer not limited to lvalues
I don't have the C89 text to compare, but the C99 description of array-to-pointer conversion (6.3.2.1/3) does not mention any restriction on the array being an lvalue. Also, the C99 section on subscripting (6.5.2.1/2) talks about the expression being subscripted as postfix expression, it does not mention lvalues either.
Consider this code:
struct foo
{
char buf[20];
};
struct foo foo(char const *p) { struct foo f; strcpy(f.buf, p); return f; }
int main()
{
char *hello = foo("hello").buf;
char *bye = foo("bye").buf;
// other stuff...
printf("%s\n", hello);
printf("%s\n", bye);
}
Where do the pointers hello and bye point to? The purpose of this clause is to say that the compiler does not have to keep all of the returned objects hanging around in memory somewhere in order to make those pointers remain valid indefinitely.
Instead, the hello is only valid up until the next ; in this case (or next sequence point in general). This leaves the compiler free to implement returning structs by value as a hidden pointer parameter, as Chris Torek describes in his excellent post, which can be "freed" at the end of the current statement.
NB. The C99 situation isn't quite as simple as described in Chris's post, as the following has to work:
printf("%s %s\n", foo("hello").buf, foo("bye").buf);
My install of gcc 4.8 seems to get it right though - that works with -std=c99, and segfaults with -std=c89.
i have a function like
void printMe (void *i)
{
printf("%d", i);
}
where i want to pass a void pointer and print it to screen.
The above example is fine if the i is integer, float or double but crashes if i is a char. There is no overloading in C like i usually use in C++.
So the question is this, can we create a function in C that will print the element that is it's parameter, and if yes how is this possible because it totally eludes me at this moment.
Q1: So the question is this, can we create a function in C that will print the element that is it's parameter
A: Not in the way you want. You will have to pass information to the function, telling it the type of data you're passing.
Q2: and if yes how is this possible because it totally eludes me at this moment.
A: It's eluding you because it can't be done. There is no metadata associated with a void* that the compiler or runtime can use to figure out they type it's pointing to. You need to either
pass a structure that contains a
pointer and information about what
the pointer points to (e.g. an
enum).
pass an extra parameter with
information about what the pointer
points to
As the code stands the only thing you can print here is the address that i points to.
A void pointer points to raw data, printf assumes you know what data type you're printing, it has no intelligence and cannot "figure it out" for you.
It's that simple.
What you can do is pass type information to the function, but then you end up with something very like printf it's self, where you pass a formatting string containing type information about the data in the following arguements.
Hope this helps.
Also . . . "There is no overloading in C like i usually use in C++"
Even in c++ the overloading happens at compile time, and here there's no way for the compiler to know what data will be passed to that function, so even though you're used to overloading, it would never work like this (e.g. try this same thing using printf, but compile it with a C++ compiler, you'll get exactly the same results).
Actually try
cout << i;
in the function above, and it will give you the address i points to, not the "value" of i.
You'd need to cast i and derference it before you could get it's value
cout << *(int*)i;
So, to get the above working in C++ you'd need to have lots of overloaded functions (or a template function, which is really the same thing, except the compiler rolls the functions for you) e.g. overloaded functions
printMe(int i){...}
printMe(double d){...}
printMe(char c){...}
printMe(char* string){...}
In c you just need to give those functions specific names
printInt(int i){...}
printDouble(double d){...}
printChar(char c){...}
printString(char* string){...}
For a start, you're printing the pointer, not what it points to. To print the actual contents, you need to pass *i to printf, not i.
If you really want to do this, one solution is:
void printMe (void *p, int typ) {
switch(typ) {
case TYP_INT: printf("%d", *((int*)p)); break;
case TYP_CHR: printf("%c", *((char*)p)); break;
/* and so on ... */
}
}
So the question is this, can we create a function in C that will print the element that is it's parameter
Yes, we can. Such a function is already part of the standard library - it's called printf ;)
As there is no compile-time function overloading in C, you somehow have to supply the type of the arguments at runtime. The printf format string can be used to do this, so there's really no reason to build your own wrapper function when there's already a working solution.
If you are trying to print out the pointer value, the correct usage is printf("%p", i);. The 'd' specifier is for integers, and the 'p' is for pointers. It's your responsibility to get these correct, and bad things can happen if you mix them up.
I don't know why this would fail for a char * and not an int *, and it is possible you've got other problems causing this. If it still fails with %p, something else got messed up. See if you can install some sort of memory monitor software to check for dangling pointers or double free()s, because at that point the smart money's that you've corrupted memory somewhere.