In the following code example:
typedef struct data{
char ch;
int n;
int n2;
}DATA;
void Func3(DATA d){
int sum;
sum = d.ch + d.n;
d.ch = 'c';
d.n = 0x77;
}
void Func4(DATA &d){
int sum;
sum = d.ch + d.n;
d.ch = 'k';
//d.n = 0x88;
}
int WINAPI WinMain(HINSTANCE hlnst, HINSTANCE hprev,
LPSTR lpCmd, int nShow)
{
DATA dt;
dt.ch = 'a';
dt.n = 10;
dt.n2 = 20;
Func3(dt);
Func4(dt);
return 0;
}
Are Func3() and Func4() the same thing?
Are both functions pass-by-reference?
Is there any difference between the two functions?
You are compiling this with a C++ compiler. DATA &d is not syntactically correct in C.
In Func, the compiler essentially writes DATA d = dt before the function body is entered.
In Func2 that "assignment" does not happen. The C++ compiler sets d to be a reference to dt. So changes to d in Func2 are reflected in the caller as changes to dt.
In your specific case though, an optimising compiler will recognise that both functions are no-ops, and so will probably compile them out.
In C there is no reference '&' type variables like in C++.
You have to pass the address to get the same affect. FUNC2() in C with 'd' as pass by reference will look like below:
void Func2(DATA *d){
int sum;
sum = d->ch + d->n;
}
When in C there is used words "pass by reference" then it means that an object is passed to a function indirectly by means of a pointer to the object.
Consider the following demonstrative program
#include <stdio.h>
void f( int *sum, int x, int y )
{
*sum = x + y;
}
void g( int sum, int x, int y )
{
sum = x + y;
}
int main( void )
{
int x = 1, y = 2;
int sum;
sum = 0;
printf( "Before call of f sum = %d\n", sum );
f( &sum, x, y );
printf( "After call of f sum = %d\n", sum );
sum = 0;
printf( "Before call of g sum = %d\n", sum );
g( sum, x, y );
printf( "After call of g sum = %d\n", sum );
}
The program output is
Before call of f sum = 0
After call of f sum = 3
Before call of g sum = 0
After call of g sum = 0
The first function, function f. accepts the argument sum by reference that is using a pointer to sum. Thus after the function call the variable sum was changed.
The second function, function g, accepts the argument sum by value that is the function deals with a copy of the argument. Thus any changes of the copy do not influence on the value of the original argument.
In C++ apart from this meaning of the words "pass by reference" in the frames of C there is additional meaning because C++ introduced the notion of references like special kind of declarators and correspondingly defined the notion of the reference type.
Thus in C++ you can one more possibility to pass a value by reference. You may use a reference type. For example you could define a function for the example above the following way
void f( int &sum, int x, int y )
{
sum = x + y;
}
In this case as the argument is passed by reference that is the corresponding parameter type is a reference type then the function will deal with the original argument instead of its copy.
.
Related
I have been searching if we can initiate an array literal with variables but couldn't find it. Bit of context, I want to pass an array literal to a function. Below is what I am trying to do:
int fun(int * a, int num){
int sum=0;
for (int i=0; i< num; ++i){
sum = sum + a[i];
}
return sum;
}
int main(){
int a = 3, b =2, c = 1 ;
int x[3] = {a,b,c}; // Is this legal? It compiles fine on all compilers I tested.
int p = fun( (int[3]){a,b,c} , 3); // I want to do something like this. pass a literal to the fucntion
return 0;
}
From the C Standard (6.7.9 Initialization)
4 All the expressions in an initializer for an object that has static
or thread storage duration shall be constant expressions or string
literals.
The string literal defined in this record
int p = fun( (int[3]){a,b,c} , 3);
has automatic storage duration. So you may initialize it with non-constant expressions in particularly using the variables a, b, and c.
Pay attention to that as the function does not change the passed array then the first parameter should have the qualifier const and to avoid overflow it is better to declare the return type as long long int.
Here is a demonstration program.
#include <stdio.h>
long long int fun( const int * a, size_t n )
{
long long int sum = 0;
for ( size_t i = 0; i < n; ++i )
{
sum += a[i];
}
return sum;
}
int main( void )
{
int a = 3, b = 2, c = 1 ;
printf( "%lld\n", fun( ( int[] ){a, b, c} , 3 ) );
}
Your code (sans the extra x array) compiles just fine with -std=c99 so yes, I'd say it's standard C99 code.
#include <stdio.h>
int fun(int a[], int num) {
int sum = 0;
for (int i = 0; i < num; ++i) {
sum = sum + a[i];
}
return sum;
}
int main() {
int a = 3, b = 2, c = 1;
int p = fun((int[3]){a, b, c}, 3);
printf("%d", p);
return 0;
}
This would not be allowed if the initializer is static, since the value needs to be assigned before the program executes. From C99:
All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.
Otherwise, each initializer needs to be an "assignment-expression" or, in other words, a valid expression that can be assigned to an object.
So yes, this is legal in C.
Well, yes. The array is being initialized as it should which can be tested by printing it.
The array is also being sent to the function properly as p returns 6. However, do note that you are making a new array to send to the function.
Can anyone explain me the difference among these two?
#include <stdio.h>
void main() {
int a = 10;
int *p = &a;
*p = 11;
}
and
#include <stdio.h>
void main() {
int a = 10;
a = 11;
}
For starters pay attention to that according to the C Standard the function main without parameters shall be declared like
int main( void )
The presented two programs actually are equivalent except that in the first program the variable a is changed through a pointer to it.
As it is written in the C Standard (6.2.5 Types, p.#20)
... A pointer type describes an object whose value provides a
reference to an entity of the referenced type.
This property of pointers is used in C to implement the mechanism of passing objects by reference to functions.
Consider the following program.
#include <stdio.h>
void f( int x )
{
x = 10;
}
void g( int *px )
{
*px = 10;
}
int main(void)
{
int x = 0;
printf( "Before calling f x = %d\n", x );
f( x );
printf( "After calling f x = %d\n", x );
x = 0;
printf( "\nBefore calling g x = %d\n", x );
g( &x );
printf( "After calling g x = %d\n", x );
return 0;
}
The program output is
Before calling f x = 0
After calling f x = 0
Before calling g x = 0
After calling g x = 10
As you can see after calling the function f the value of the variable x declared in main was not changed. The problem is that the function deals with a copy of the value of the variable x declared in main. That is the function parameter is a local variable of the function that was initialized by the value of the variable x declared in main. Changing the local variable does not influence on the variable x declared in main.
But when the variable x is passed to the function g by reference through a pointer to it then the function is able to change the original variable x declared in main by means of dereferencing the passed pointer.
Also bear in mind that when you allocate a memory dynamically then allocated objects do not have names. You only have pointers to dynamically allocated objects. For example
int *px = malloc( sizeof( int ) );
So to change the allocated object you also need to dereference the pointer
*px = 10;
In this case nothing, but suppose that you want to call a function, if want to edit the value of a FROM INSIDE that function, you'll need to use pointers.
#include <stdio.h>
void set_a(int *p, int val)
{
*p = val;
}
int main()
{
int a = 2;
printf("a is: %d\n", a); // a is 2
set_a(&a, 5);
printf("a is: %d\n", a); // a is 5
}
that's just one use case. for instance, when using heap allocations, you'll need to use pointers.
The two programs have the same observable effect.
What is the purpose of using pointer to change the value of mutable object?
One good use is to be able to reuse logic. Write it once and use it many times.
Example:
void foo(int *X, int *Y) {
/* some complex calculation */
*X = *X + *Y + 1;
*Y = *Y + *X + 2;
}
Now, you could use the function to do this "complex" calculation on different variables. You only need to write and test it properly once and can then reuse it many times.
int main() {
int a = 10, b = 20, c = 30, d = 40;
foo(&a, &b);
foo(&c, &d);
//...
}
Demo
#include <stdio.h>
float orizousa(int n[]);
int main() {
int a[12];
int i;
printf("grapse tous sintelestes kai to apotelesma tis prwtis eksiswsis \n (me seira:1os-2os-3os sintelestis - apotelesma) :");
for(i=0; i<=11; i++) {
scanf(" %d",&a[i]);
}
float g = orizousa(a);
printf(" %f",g);
return 0;
}
float orizousa(int a[]) {
float d,dx1,dx2,dx3,x1,x2,x3;
d = a[0]*a[4]*a[8] + a[1]*a[5]*a[6] + a[2]*a[3]*a[7] - a[2]*a[4]*a[7] - a[1]*a[3]*a[8] - a[0]*a[5]*a[7] ;
dx1 = a[9]*a[4]*a[8] + a[1]*a[5]*a[11] + a[2]*a[10]*a[7] - a[2]*a[4]*a[7] - a[1]*a[10]*a[8] - a[9]*a[5]*a[7] ;
dx2 = a[0]*a[10]*a[8] + a[0]*a[5]*a[6] + a[2]*a[3]*a[11] - a[2]*a[10]*a[11] - a[1]*a[3]*a[8] - a[0]*a[5]*a[11] ;
dx3 = a[0]*a[4]*a[11] + a[1]*a[10]*a[6] + a[9]*a[3]*a[7] - a[9]*a[4]*a[7] - a[1]*a[3]*a[11] - a[0]*a[10]*a[7] ;
return d;
}
In this code, in the line that says
float g = orizousa(a);
why do we put only a in, and not a[] for example??
How can I return 2 values, for example d and dx, from one function??
when it comes to array just the name, passes the array's address and the function accepting it will be pointing to the same memory address. it more like reference variable in C++.
u cant return more than one value at a time. if the data is of similar type u can copy to an array and pass the array back
Arrays and pointers are intimately related. When you write "g=orizousa(a)" you are passing the function a copy of the address of the first element of the array a.
To return two values from a function you can either pass the address of the two variables you want to change or put them into a structure and return the structure.
void foo( int* x, int* y ) {
*x = 1; *y = 2;
}
called as
int xx = 0;
int yy = 0;
foo(&xx,&yy);
or as a struct
typedef struct {
int x;
int y;
} args;
either pass in as argument
void foo(args* arg) {
args.x=1;
args.y=2;
}
called as
args arg;
foo(&arg);
or returned
args foo() {
args arg = { 1,2 };
return arg;
}
called as
args arg = foo();
float g=orizousa(a);
int a[]
a is an array of integer type where the variable name 'a' denotes the reference of array a.
function orizousa takes a reference parameter of integer type. thats why you have to pass a instead of a[]
if you want to return d and dx then simply add another reference to your function.
orizousa(int a[],float pReturn[])
{
....
pReturn[0]=d;
pReturn[1]=dx;
}
why we put only 'a' in, and not a[] for example??
When passing array as arguments to functions in C, we have to pass the variable name only, unless you want to pass only one element of the array, which in that case would be float g = orizousa(a[2]) for example. But the function orizousa receives an array, so you have to pass the entire array.
and how can i return 2 values??
There is no way to return 2 values in C from a function. But what you can do is pass variables as reference. You can do something like this:
#include <stdio.h>
float orizousa(int n[]);
int main()
{
int a[12];
int i;
printf("grapse tous sintelestes kai to apotelesma tis prwtis eksiswsis \n (me seira:1os-2os-3os sintelestis - apotelesma) :");`enter code here`
for(i=0;i<=11;i++)
{ scanf(" %d",&a[i]);}
float d, dx1, dx2, dx3;
float g=orizousa(a, &d, &dx1, &dx2, &dx3);
printf(" %f",g);
return 0;
}
float orizousa(int a[], float *d, float *dx1, float *dx2, float *dx3)
{
*d=a[0]*a[4]*a[8] + a[1]*a[5]*a[6] + a[2]*a[3]*a[7] - a[2]*a[4]*a[7] - a[1]*a[3]*a[8] - a[0]*a[5]*a[7] ;
*dx1=a[9]*a[4]*a[8] + a[1]*a[5]*a[11] + a[2]*a[10]*a[7] - a[2]*a[4]*a[7] - a[1]*a[10]*a[8] - a[9]*a[5]*a[7] ;
*dx2=a[0]*a[10]*a[8] + a[0]*a[5]*a[6] + a[2]*a[3]*a[11] - a[2]*a[10]*a[11] - a[1]*a[3]*a[8] - a[0]*a[5]*a[11] ;
*dx3=a[0]*a[4]*a[11] + a[1]*a[10]*a[6] + a[9]*a[3]*a[7] - a[9]*a[4]*a[7] - a[1]*a[3]*a[11] - a[0]*a[10]*a[7] ;
}
When you are passing an array to the function orizousa, you are passing the address of the array, not an actual copy (atleast in this case). In C, a actually stores the address of the first element of the array. So, you are passing the address of the first element of the array. *a will print the value of the first element. we cannot pass a[] because that is a syntax error.
To return 2 values, you can declare a variable in the main function and pass it as a reference variable to orizousa. Then you can return d and store the value of dx1 in the reference variable.
i find this in Pointers on C
int f[](); /* this one is illegal */
and:
int (* f [])(); /* this one legal. */
i really want know what's the usage of the second one.
thank you.
The second example is quite valid, if you use initialization block. For example:
#include <stdio.h>
int x = 0;
int a() { return x++ + 1; }
int b() { return x++ + 2; }
int c() { return x++ + 3; }
int main()
{
int (* abc[])() = {&a, &b, &c};
int i = 0,
l = sizeof(abc)/sizeof(abc[0]);
for (; i < l; i++) {
printf("Give me a %d for %d!\n", (*abc[i])(), i);
}
return 0;
}
I'm not sure if the second example is legal, since the size of the function array is not known, but what it is supposed to be is an array of function pointers, and here is a possible example of usage if the size would be known:
int a()
{
return 0;
}
int main(int argc ,char** argv)
{
int (* f [1])();
f[0] = a;
}
int f[](); // this is illegal because of you can't create array of functions . It's illegal in C
But second is legal
int (* f [])(); It says that f is an array of function pointers returning int and taking unspecified number of arguments
int f[](); /* this one is illegal */
That's trying to declare an array of functions, which is impossible.
int (* f [])(); /* this one NOT legal, despite what the OP's post says. */
That's trying to declare an array of function pointers, which would be perfectly legal (and sensible) if the array size were specified, e.g.:
int (* f [42])(); /* this one legal. */
EDIT: The type int (* f [])() can be used as a function parameter type, because for function parameter types, array-to-pointer conversion takes place immediately, meaning we don't ever need to specify the dimension of the innermost array of a (possibly multidimensional) array:
void some_func(int (* f [])()); /* This is also legal. */
I have:
#include <stdio.h>
int sum ( int x, int y );
main ()
{
int theSum = sum (10, 11);
printf ( "Sum of %i and %i is: %i\n", x, y, theSum );
}
int sum ( int x, int y )
{
return x + y;
}
However, when I compile and run it says x and y are undeclared? Any help greatly appreciated. Thanks
In line three all you have done is declare a function sum which takes two parameters, both integers, called x and y. You haven't declared any variables. Those parameters can only be referred to inside the function itself. Below is a simplification which will help you at this stage, but you should try to read a basic programming book. "The C Programming Language" by Kernighan and Ritchie is a fine place to start.
Variables are chunks of memory that you refer to by name. They can take on any value (of their type) during the life of your program - hence the name 'variable'. They must be declared before you use them; you do this by telling the compiler their type and their name. int a means 'reserve me a block of memory big enough to hold any integer, and let me refer to it later with the name a'. You can assign values to it: a = 10 and you can make use of it: a + 20.
You need to understand the difference between parameters and variables to get what's going on here. A function's parameters are basically variables which exist only during the life of that function. Here's your sum again:
int sum(int x, int y) {
return x + y;
}
Notice how the top line looks just like a variable declaration int x. That's because it is. x and y are variables you can use in the function.
You call sum by passing in values. The compiler, in effect, replaces x and y in your function with the values you pass in. In your case, you're passing literals: 10 and 11. When the program reaches the call to sum, the parameters x and y take on the values 10 and 11, so the return becomes return 10 + 11; which is of course 21.
Just remember that the parameters x and y only exist in that function. You may only refer to them within your function. Why? Because each pair of curly braces { and } define a scope, and anything declared within that scope can only be used within that scope. That includes variables and parameters.
So, here is a more complete example. I have changed the letters so you can see the different ways you use variables and parameters:
#include <stdio.h>
int sum ( int x, int y );
main ()
{
/* We declare our variables */
int a;
int b;
/* We assign values to them */
a = 10;
b = 11;
/* We pass them as parameters to your sum function */
int theSum = sum (a, b);
/* And we use them as parameters again, in a call to the printf function */
printf ( "Sum of %i and %i is: %i\n", a, b, theSum );
}
int sum ( int x, int y )
{
return x + y;
}
declare x and y right before the call to sum:
main ()
{
int x = 10;
int y = 11;
int theSum = sum (x, y);
printf ( "Sum of %i and %i is: %i\n", x, y, theSum );
}
You would have to declare x and y in main, so that you call sum(x,y) rather than calling it on 2 literals. At the moment, x and y are only defined in the function sum.
No, you haven't. You just told the compiler that the function sum takes two ints. You could have written that as
int sum ( int , int );
Therefore you should write:
#include <stdio.h>
int sum ( int , int );
main ()
{
int x = 10;
int y = 11;
int theSum = sum (x, y);
printf ( "Sum of %i and %i is: %i\n", x, y, theSum );
}
int sum ( int x, int y )
{
return x + y;
}
The x and y variables are only passed as arguments to the function. You would not be able to reference those in the main function. If you wanted to, it would be like this:
#include <stdio.h>
int sum ( int x, int y );
main ()
{
int x = 10;
int y = 11;
int theSum = sum (x, y);
printf ( "Sum of %i and %i is: %i\n", x, y, theSum );
}
int sum ( int x, int y )
{
return x + y;
}
This should work. I hope this helps!
In your main you’re declaring neither x nor y—you’re just passing in the literal values 10 and 11. Outside the scope of the sum method, neither name has any meaning. Quick fix:
main()
{
int x = 10;
int y = 11;
int theSum = sum(x, y);
// etc.