swap using pointers

Z

Zach

I am working on a new version of my swap program [1] that uses
pointers. It seems to work fine but I have some points I would like
clarifying.

Here is the code:

/* swap-foo2.c: swap 2 integers
* Zach
* 01/27/08, version 2
*/

#include <stdio.h>
#include <stdlib.h>

int swap(int*, int*);

int *s1, *s2;

int main(void)
{

s1 = 3;
s2 = 4;

printf("s1 = %d \n", s1);
printf("s2 = %d \n", s2);

swap(s1,s2);

exit(EXIT_SUCCESS);

}

int swap(int *s1, int *s2)
{
int temp;

temp = s1;
s1 = s2;
s2 = temp;

printf("s1 = %d \n", s1);
printf("s2 = %d \n", s2);

return s1,s2;

}

When I compile and run it:

zu22@netrek:~/src/myc$ gcc -g -o foo swap-foo2.c
swap-foo2.c: In function 'main':
swap-foo2.c:16: warning: assignment makes pointer from integer without
a cast
swap-foo2.c:17: warning: assignment makes pointer from integer without
a cast
swap-foo2.c: In function 'swap':
swap-foo2.c:32: warning: assignment makes integer from pointer without
a cast
swap-foo2.c:34: warning: assignment makes pointer from integer without
a cast
swap-foo2.c:39: warning: return makes integer from pointer without a
cast

zu22@netrek:~/src/myc$ ./foo
s1 = 3
s2 = 4
s1 = 4
s2 = 3

I had been told by a member of this group, Joachim Schmitz, to call my
swap function with the address of my two variables:
swap(&s1,&s2);

However when I do this it gives some new warnings and a strange
result:

zu22@netrek:~/src/myc$ gcc -g -o foo swap-foo2.c
swap-foo2.c: In function 'main':
swap-foo2.c:16: warning: assignment makes pointer from integer without
a cast
swap-foo2.c:17: warning: assignment makes pointer from integer without
a cast
swap-foo2.c:22: warning: passing argument 1 of 'swap' from
incompatible pointer type
swap-foo2.c:22: warning: passing argument 2 of 'swap' from
incompatible pointer type
swap-foo2.c: In function 'swap':
swap-foo2.c:32: warning: assignment makes integer from pointer without
a cast
swap-foo2.c:34: warning: assignment makes pointer from integer without
a cast
swap-foo2.c:39: warning: return makes integer from pointer without a
cast

zu22@netrek:~/src/myc$ ./foo
s1 = 3
s2 = 4
s1 = 134518352
s2 = 134518348

Why is this? I'm doing this to help advance my understanding of
pointers and passing parameters to functions. Can someone explain what
all these warnings mean?

BTW on lines 16, 17 where I assign values to the pointers why can't I
do this:
*s1 = 3;
*s2 = 4;

When I do it causes a core dump:

zu22@netrek:~/src/myc$ gcc -g -o foo swap-foo2.c
swap-foo2.c: In function 'main':
swap-foo2.c:22: warning: passing argument 1 of 'swap' from
incompatible pointer type
swap-foo2.c:22: warning: passing argument 2 of 'swap' from
incompatible pointer type
swap-foo2.c: In function 'swap':
swap-foo2.c:32: warning: assignment makes integer from pointer without
a cast
swap-foo2.c:34: warning: assignment makes pointer from integer without
a cast
swap-foo2.c:39: warning: return makes integer from pointer without a
cast

zu22@netrek:~/src/myc$ gdb ./foo
GNU gdb 6.6.90.20070912-debian
Copyright (C) 2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/
gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show
copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) run
Starting program: /home/zu22/src/myc/foo
Failed to read a valid object file image from memory.

Program received signal SIGSEGV, Segmentation fault.
0x080483ba in main () at swap-foo2.c:16
16 *s1 = 3;
(gdb) bt
#0 0x080483ba in main () at swap-foo2.c:16
(gdb) quit
The program is running. Exit anyway? (y or n) y

I've seen pointer values assigned in this way with type char as in:
char *string = "hello";
So why is this illegal with type int?

Also I noticed if I print out the values of my pointer variables in
main after the call to swap they are still the same. My understanding
was that since I declared them as global variables they had global
scope and when swap returns the new values they should be changed but
it seems they aren't here:

/* swap-foo2.c: swap 2 integers
* Zach
* 01/27/08, version 2
*/

#include <stdio.h>
#include <stdlib.h>

int swap(int*, int*);

int *s1, *s2;

int main(void)
{

s1 = 3;
s2 = 4;

printf("s1 = %d \n", s1);
printf("s2 = %d \n", s2);

swap(s1,s2);

printf("s1 = %d \n", s1);
printf("s2 = %d \n", s2);

exit(EXIT_SUCCESS);

}

int swap(int *s1, int *s2)
{
int temp;

temp = s1;
s1 = s2;
s2 = temp;

return s1,s2;

}

zu22@netrek:~/src/myc$ gcc -g -o foo swap-foo2.c
swap-foo2.c: In function 'main':
swap-foo2.c:16: warning: assignment makes pointer from integer without
a cast
swap-foo2.c:17: warning: assignment makes pointer from integer without
a cast
swap-foo2.c: In function 'swap':
swap-foo2.c:35: warning: assignment makes integer from pointer without
a cast
swap-foo2.c:37: warning: assignment makes pointer from integer without
a cast
swap-foo2.c:39: warning: return makes integer from pointer without a
cast

zu22@netrek:~/src/myc$ ./foo
s1 = 3
s2 = 4
s1 = 3
s2 = 4

My understanding is that in the following code:

int main(void)
{

int *p; /* or "int* p" declares a variable p pointing to type int */

int q; /* declares variable q of type int */

p = 3; /* assigns the integer 3 as the pointer-value */

foo(&p): /* the function foo calls the address of the pointer p's
location in memory,
by using the address-of operator &.
this represents the starting bit of where it is layed
out in memory */

q = *p; /* assigns the pointer-value to point to variable q,
by using the dereferencing operator *. */

}

Are all my comments correct?

PS: I noticed in "man 3 printf" that %p is for pointers and not %d but
when I use that it prints my results in hexadecimal such as:
s1 = 0x3
s2 = 0x4

[1] http://tinyurl.com/2zh5mj

Regards,
Zach
 
R

Richard Heathfield

Zach said:
I am working on a new version of my swap program [1] that uses
pointers. It seems to work fine but I have some points I would like
clarifying.

Here is the code:

Here is the fixed code:

/* swap-foo3.c: swap 2 integers
* rjh - changes are marked.
* 01/28/08, version 3
*/

#include <stdio.h>
#include <stdlib.h>

int swap(int*, int*);

int main(void)
{

int s1 = 3; /* int, not int *, okay? */
int s2 = 4; /* and again */

printf("Before swap, s1 = %d\n", s1); /* clarify meaning */
printf("Before swap, s2 = %d\n", s2); /* of print */

swap(&s1, &s2); /* pass addresses */

printf("After swap, s1 = %d\n", s1); /* display results */
printf("After swap, s2 = %d\n", s2); /* after swap */

exit(EXIT_SUCCESS); /* this is okay, but I'd prefer return 0; */

}

int swap(int *s1, int *s2)
{
int temp;

temp = *s1; /* we're swapping the values of the objects pointed to */
*s1 = *s2; /* To get to those values, we use the *deref operator */
*s2 = temp; /* here too */

return 0; /* I don't know why you thought you could return s1,s2 */
}
 
S

santosh

Zach said:
I am working on a new version of my swap program [1] that uses
pointers. It seems to work fine but I have some points I would like
clarifying.

Here is the code:

/* swap-foo2.c: swap 2 integers
* Zach
* 01/27/08, version 2
*/

#include <stdio.h>
#include <stdlib.h>

int swap(int*, int*);

int *s1, *s2;

int main(void)
{

s1 = 3;
s2 = 4;

This invokes implementation specific behaviour. Integers are not
automatically convertible to pointer values. At a minimum, you need to
use a cast. However you'll find that for most modern desktop operating
systems, the code will still malfunction, even after a cast.

In general you cannot use an arbitrary memory address under memory
protected multitasking OSes. You must let the compiler and runtime
library take of such stuff and initialise pointers only to the address
yielded by the address-off operator '&' applied on an object of
compatible type and scope, or assign the return value of the *alloc()
functions, malloc(), calloc() or realloc().
printf("s1 = %d \n", s1);
printf("s2 = %d \n", s2);

The format specifier for printing pointer values is 'p'. It accepts a
void * value. Use like:

printf("s1 = %p\n", (void *)s1);
swap(s1,s2);

Not only are you accessing arbitrarily chosen addresses (which will most
likely lead to a segmentation fault under most desktop OSes), but you
are accessing indeterminate values as well.
exit(EXIT_SUCCESS);

}

int swap(int *s1, int *s2)
{
int temp;

temp = s1;

This should be:

temp = *s1;

*s1 = *s2;
s2 = temp;

*s2 = temp;
printf("s1 = %d \n", s1);
printf("s2 = %d \n", s2);

These should be:

printf("s1 = %d\n", *s1);
ditto
return s1,s2;

Huh? What the hell is the purpose of this? s1 and s2 are both int *
values, but you define swap() as returning an int value. At a minimum
you need to do:

return *s1, *s2;

This is still silly in the sense that this will evaluate *s1 and discard
the value, returning *s2;
}

When I compile and run it:

zu22@netrek:~/src/myc$ gcc -g -o foo swap-foo2.c

Also use the '-Wall', '-W', '-ansi' and '-pedantic' switches. They will
tell gcc to conform strictly to C95 and turn on a lot of diagnostics
(though not all).

Please read a good textbook on C like K&R2 or a good online tutorial
like Steve Summit' or Tom Torf' before proceeding. You are making
several fundamental errors that a good book or tutorial can more easily
correct than a newsgroup.

<rest snipped>
 
M

Mark Bluemel

santosh said:
Please read a good textbook on C like K&R2 or a good online tutorial
like Steve Summit' or Tom Torf' before proceeding. You are making
several fundamental errors that a good book or tutorial can more easily
correct than a newsgroup.

We do seem to have a certain proportion of posters who believe that C
programming can be successfully learnt by trial and error, supplemented
by posting their code - which bears a passing resemblance to C,
indicating that they've seen some C code but not understood it - to this
newsgroup...
 
P

pete

Richard said:
Zach said:
I am working on a new version of my swap program [1] that uses
pointers. It seems to work fine but I have some points I would like
clarifying.

Here is the code:

Here is the fixed code:

/* swap-foo3.c: swap 2 integers
* rjh - changes are marked.
* 01/28/08, version 3
*/

#include <stdio.h>
#include <stdlib.h>

int swap(int*, int*);

int main(void)
{

int s1 = 3; /* int, not int *, okay? */
int s2 = 4; /* and again */

printf("Before swap, s1 = %d\n", s1); /* clarify meaning */
printf("Before swap, s2 = %d\n", s2); /* of print */

swap(&s1, &s2); /* pass addresses */

printf("After swap, s1 = %d\n", s1); /* display results */
printf("After swap, s2 = %d\n", s2); /* after swap */

exit(EXIT_SUCCESS); /* this is okay, but I'd prefer return 0; */

}

int swap(int *s1, int *s2)
{
int temp;

temp = *s1; /* we're swapping the values of the objects pointed to */
*s1 = *s2; /* To get to those values, we use the *deref operator */
*s2 = temp; /* here too */

return 0; /* I don't know why you thought you could return s1,s2 */
}

It should really be
void swap(int *s1, int *s2)
There is no information in the return value from that function.
 
K

Keith Thompson

santosh said:
Zach wrote: [...]
int *s1, *s2;

int main(void)
{

s1 = 3;
s2 = 4;

This invokes implementation specific behaviour. Integers are not
automatically convertible to pointer values. At a minimum, you need to
use a cast. However you'll find that for most modern desktop operating
systems, the code will still malfunction, even after a cast.

This doesn't merely invokes implementation specific behavior.
Attempting to assign an int value (other than a constant 0) to a
pointer is a constraint violation. There is no implicit conversion
from integers to pointers or vice versa, except for ones involving
null pointer constants. *If* the implementation chooses to accept the
assignments (after issuing a mandatory diagnostic), the behavior is
undefined by the standard; it might not even do a conversion.

As Richard points out, the proper solution isn't for the OP to
understand the gory details of just how and why the assignments are
wrong and exactly what effect they can have, it's to write the correct
code in the first place.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top