antiloquax
Posts: 406
Joined: Sun Nov 20, 2011 11:37 am
Contact: Website

Little program - pointers

Mon Jun 04, 2012 3:07 pm

I've been using a variety of different resources as I try to learn a bit of C. Namely:
Learn C the Hard Way (Zed A Shaw).
The Gnu C Tutorial
Hacking: The Art of Exploitation

Today I stumbled across an excellent series of lectures by Jerry Cain.
This link points at the third one, in which he describes using pointers to do a little swap function. I thought I'd have a go at coding it and came up with this.

Code: Select all

#include <stdio.h>
// swap function

void swap_nums(int *, int *);       // prototype a function that takes pointers.

int main()
{
    int x = 10;
    int y = 66;
    printf("x = %d y= %d\n", x, y);
    swap_nums(&x, &y);         // pass the addresses of x and y to my function
    printf("x = %d y= %d\n", x, y);
    return 0;
}

void swap_nums(int *a, int *b)
{
    int c;
    c = *a;     
    *a = *b;  
    *b = c;
}

So, if I have got this right:
I pass pointers to my function.
"a" stores the memory location where 10 is stored and "b" the address where I have 66 stored.
c = *a
The asterisk "dereferences" the pointer - in other words now the actual value at that address is put into "c".
*a = *b
The value held at address a is made to equal the value held at address b.
*b = c
The value held at address b is made to equal c (just an int, not a pointer!)
Then we return to main and the values have been swapped!
:)

User avatar
rurwin
Forum Moderator
Forum Moderator
Posts: 4258
Joined: Mon Jan 09, 2012 3:16 pm
Contact: Website

Re: Little program - pointers

Mon Jun 04, 2012 4:50 pm

Yes, you have that right.

Also an array is a (constant) pointer to the first in a list of values.

int a[10];

defines a list of ten integers.
*a is the first integer in the list.
a[0] is also the first integer in the list.

You can add a number to a pointer and it will give the address of the next item in the list.

*(a+1) is the second integer in the list.
a[1] is also the second integer in the list.

However a is a constant, so you cannot say

int *b;
a = b; // ERROR

This is why you will often see code like this:

Code: Select all

void printstring (char* str)
{
    printf("%s\n", str);
}

void main (int argc, char** argv)
{
    char string[100] = "My String"
    printstring (string);
    printstring (argv[0]);
}
string is declared as an array of char, but when you use it as a parameter to a function it turns into a pointer to char.

Similarly, argv is a pointer to a pointer to char. argv[0] (or *argv) is a pointer to char, which is a string.

You can also get the address of a value by using "&":

int b;
int *a;
a = &b;
b = 42;
printf("%d\n", *a); // prints 42

User avatar
rurwin
Forum Moderator
Forum Moderator
Posts: 4258
Joined: Mon Jan 09, 2012 3:16 pm
Contact: Website

Re: Little program - pointers

Mon Jun 04, 2012 5:31 pm

Another nice lesson to go with the OP is about the three ways of passing parameters. Most languages use two of them and do so explicitly. C uses all three and does so implicitly. That means it is easy to see how it works. Other languages work the same way but hide all the complicated details.

Passing by value

Code: Select all

void f(int a)
{
    a = 3;
   printf ("%d\n", a);  // prints 3
}

main()
{
  int x=2;
  f(x);
  printf ("%d\n", x);  // prints 2
}
Only the value of x is passed to the function. Changing the value in the function does not change the value of the variable that was passed in.

Passing by Reference

Code: Select all

void f(int *a)
{
    *a = 3;
   printf ("%d\n", *a);  // prints 3
}

main()
{
  int x=2;
  f(&x);
  printf ("%d\n", x);  // prints 3
}
A pointer to the value is passed in to the function, so the function can change the value of the variable that was passed in.

Passing by Name

Code: Select all

#define f(a,b) b = a + a

main()
{
    int x=2, y;
    f(++x,y);
   printf ("%d\n", y);  // prints 7
}
This is a tough one to wrap your head around. Every time the parameter appears in the macro it is executed again. Here the macro uses "a" twice, so the ++ operator is executed twice. We can see that if we do the job of the preprocessor and expand the macro:

y = ++x + ++x

after the first ++, x=3, after the second x=4, so y is set to 7.

Very few languages use passing by name for real functions because it is difficult to implement. Algol is the only one I know of that does it. The C macros are not quite perfect implementations, but fairly close.

andyl
Posts: 265
Joined: Tue Jan 10, 2012 11:05 am

Re: Little program - pointers

Tue Jun 05, 2012 12:45 am

rurwin wrote: Passing by Name

Code: Select all

#define f(a,b) b = a + a

main()
{
    int x=2, y;
    f(++x,y);
   printf ("%d\n", y);  // prints 7
}
This is a tough one to wrap your head around. Every time the parameter appears in the macro it is executed again. Here the macro uses "a" twice, so the ++ operator is executed twice. We can see that if we do the job of the preprocessor and expand the macro:

y = ++x + ++x

after the first ++, x=3, after the second x=4, so y is set to 7.

Very few languages use passing by name for real functions because it is difficult to implement. Algol is the only one I know of that does it. The C macros are not quite perfect implementations, but fairly close.
I would disagree with this. The #define isn't really a function it is a function-like macro, It works by textual substitution. I would also say the very few languages use call-by-name for real functions because most language developers are sane - Algol's call-by-name is widely regarded as a misfeature.

Also the example is very bad C. The expanded line y = ++x + ++x exhibits undefined behaviour.

antiloquax
Posts: 406
Joined: Sun Nov 20, 2011 11:37 am
Contact: Website

Re: Little program - pointers

Tue Jun 05, 2012 1:54 pm

Thanks for your replies. I've been watching more of Prof. Cain's videos and I've made myself a little generic swap function.

Code: Select all

#include <stdio.h>
#include <string.h>
// generic swap function
void swap_nums(void *, void *, int);
int main()
{
    double x = -3.333333;
    double y = 99.5;
    printf("x = %f y= %f\n", x, y);
    swap_nums(&x, &y, (sizeof(x)));
    printf("x = %f y= %f\n", x, y);
    printf("\n\n");
    
    short i = 12;
    short j = 200;
    printf("i = %d j= %d\n", i, j);
    swap_nums(&i, &j, (sizeof(i)));
    printf("i = %d j= %d\n", i, j);
    printf("\n\n");
    
    char n = 'a';
    char m = 'z';
    printf("n = %c m= %c\n", n, m);
    swap_nums(&n, &m, (sizeof(n)));
    printf("n = %c m= %c\n", n, m);
    printf("\n\n");
    
    return 0;
}

void swap_nums(void *vp1, void *vp2, int size)
{
    char buffer[size];
    memcpy(buffer, vp1, size);
    memcpy(vp1, vp2, size);
    memcpy(vp2, buffer, size);
}
This compiles and runs - the function deals with doubles, shorts, chars etc.
It was a it lazy of me to leave the function name as "swap_nums" :oops:
I am learning a hell of a lot from this guy's lectures!

Mjiig
Posts: 21
Joined: Mon Dec 05, 2011 8:44 pm

Re: Little program - pointers

Tue Jun 05, 2012 3:38 pm

antiloquax wrote:I've been using a variety of different resources as I try to learn a bit of C. Namely:
Learn C the Hard Way (Zed A Shaw).
The Gnu C Tutorial
Hacking: The Art of Exploitation
Somewhere along the line you'll probably want to read K&R's "The C Programming Language". It's a little out of date now (the second edition is the most recent and was written for C89), but it goes into a fair bit of depth into every feature of the language at that point, and also explains the exact syntax rules a great deal better than anything else I've seen for a number of features.
They also make quite heavy use of example code to demonstrate every feature, mostly not with arbitrary "This is what happens when I put data in an array and then read it again" style examples, but by writing practical (if sometimes redundant) functions to implement things such as printf and qsort.

antiloquax
Posts: 406
Joined: Sun Nov 20, 2011 11:37 am
Contact: Website

Re: Little program - pointers

Tue Jun 05, 2012 4:24 pm

Hi Mjiig,

Yes, I have that book. I found the exercises a bit too difficult. I'll go back to it when I've learned more, I think.
mark

Return to “C/C++”