Complete.Org: Mailing Lists: Archives: linux-help: April 2001:
[linux-help] Re: C HELP(out of list-subject)
Home

[linux-help] Re: C HELP(out of list-subject)

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: linux-help@xxxxxxxxx
Subject: [linux-help] Re: C HELP(out of list-subject)
From: Tom Hull <thull@xxxxxxxxxxx>
Date: Mon, 30 Apr 2001 00:34:55 -0500
Reply-to: linux-help@xxxxxxxxx

Weqaar Ali Janjua wrote:
> 
> Thanks a lot for the help!:)  and to John Reinke
> 
>   Sorry 4 replying late as I was sick N could'nt check my email!!:)
> anyways, Well I understand what u stated clearly, the following program
> does help, now what confuses me a lot is when I hold a pointer equal to a
> memory address like:
> 
> char *hackPtr;
> hackPtr=0xFFF0;

You should never do this (assign an integer value to a pointer). The only
valid rvalues that can be safely assigned to a pointer are:

  1) Pointers obtained by using the & operator on an lvalue. Example:

       int foo;
       int *fooptr = &foo;

  2) Pointers obtained by calling malloc(), using a cast.

       int *fooptr = (int*) malloc(10 * sizeof(int));

  3) Pointers obtained from other pointer expressions.

       int foo, foov[10];
       int *fooptr, *fooptr2, *fooptr3;

       fooptr = &foov[0];
       fooptr2 = fooptr;
       fooptr3 = foov;

Note that in all of these cases fooptr is being initialized to the address of
an object in your address space. Arbitrary integer values may or may not be
in your address space, but as a programmer you cannot know that.

There are some very rare exceptions to these rules, but only if you are writing
something like a device driver in a machine that does not map virtual addresses.

> Now according to a howto on a wesbite, when u = a pointer to a memory
> address like the above statement it starts pointing to that address, but
> does the pointer really starts pointing to that address like that???

An address is an unsigned number. A pointer is a variable that contains an
address. A valid pointer (or valid pointer expression) can be used to find
a value in memory (an object), and can read or write that value. We call
this dereferencing the pointer: the dereferencing operator is * (conversely,
we can take a reference to an object with the & operator).

It is critical that you understand that not every valid unsigned integer value
is a valid address: the only valid addresses that you program can access are
the virtual addresses that the operating system maps for your process address
space. (See /proc/*/maps for a table of these, replace * with the process ID
that you are interested in. The addresses are the first two hexadecimal 
numbers.)
Ergo, you cannot just pull numbers out of your hat and expect them to be valid
addresses.

The other important thing about pointers is that each pointer (except void*)
points to an object of a particular type (e.g., int *ptr; is a variable named
ptr that can contain the address of an integer object). You have to be very
careful that any pointer that you use only points to an object of the same
type as the pointer.

> Now according to TOM HULL <thull@xxxxxxxxxxx>, If it looks like
> I'm getting persistent storage when I exit my program and get the same data
> from the same addresses when I run my program again, that's an illusion,
> just luck.!! I GET THAT, thats right, I tried it in linux I get different
> addresses most of the times BUT BUT BUT when I run my following program to
> modify/read a value in a certain location (what I tried to do was I
> executed my first program and after inputting the values into the mem.
> locations and getting the addresses I did'nt exit my prog. instead keep it
> running in a nonsense loop so the data remains in those mem. addresses),
> suppose I get a mem. location of 0x0004 :
> 
> #include <stdio.h>
> #define HACK_ADDR 0x0004
> int main(void)
> {
> int *hackPtr;
> hackPtr=HACK_ADDR;
> scanf("%d",hackPtr); // Yeah gets() is dangerous

gets() is dangerous, but scanf() is stupid. You want to use fgets() to read
a line without danger of overflowing the buffer (but you still need to check),
and sscanf() to convert the string you read into an integer.

> printf("\nvalue is %d and address is %p\n",hackPtr,hackPtr);

This, on the other hand, is a really serious mistake. The first %d is replaced
with the value of hackPtr, which is the pointer address that you entered, as
a decimal number; the %p is replaced with the value of hackPtr, which is the
same value as the %d, except that it is probably printed out in hexadecimal.

You should realize that printf() is just a function, and that the arguments
separated by commas are just expressions. Technically, printf() is declared
as:

  int printf(const char*, ...);

Which means that the compiler does not care what the 2nd, 3rd, etc., arguments
are. In particular, it does not look at the format string -- the 1st argument,
which is normally checked to see if it is convertible to (const char*) -- to
help it decide what to do with the rest of the arguments.

It seems like what you're trying to do here is more like:

  printf("the pointer address is %p and the integer value at that address is 
%d",
         hackPtr, *hackPtr);

> return 0;
> }
> 
> Now the strange thing(to me:) happens is if I input supposing a
> integer(tried to use int values instead of char!!) "3" the mem. location I
> get is always 0x0003 and if I input "9" the mem. locations I get is 0x0009
> ....anyways still stuck on HOW TO MODIFY DATA IN A MEMORY LOCATION!!

As Greg House has already replied, this example will core dump on a Linux
machine.

More generally, there are no addresses that a human can know that can be
entered into your program with certainty that they will be valid.

> I'm still trying, lets try try again!, I'll get it one day!!
> Thanks to all ya guyz,
> Weqaar

Try the following program:

  #include <stdio.h>
  #define MAX_I 10

  int main()
  {
    char inbuf[128];
    int foov[MAX_I], *fooptr;
    int i;

    for (i = 0; i < MAX_I; i++) {
      foov[i] = i * i;
    }
    for ( ; ; ) {
      printf("enter a number from 0 to 9: ");
      if (fgets(inbuf, sizeof inbuf, stdin)) {
        sscanf(inbuf, "%d", &i);
        if (i < 0 || i >= MAX_I) {
          printf("%d is out of range, try again\n", i);
        }
        else {
          fooptr = foov + i;
          printf("foov: %u, &foov[%d]: %u, foov[%d]: %d\n", foov, i, &foov[i],
                 i, foov[i]);
          printf("fooptr: %u, *fooptr: %d\n", fooptr, *fooptr);
        }
      }
      else break;
    }
    return 0;
  }

Caveat emptor: I didn't even try compiling this program, but it should be
simple and clear. The program will normally terminate on EOF; e.g., ^D from
your terminal.

-- 
/*
 *  Tom Hull * thull at kscable.com * http://www.ocston.org/~thull/
 */
-- This is the linux-help@xxxxxxxxx list.  To unsubscribe,
visit http://tmp2.complete.org/cgi-bin/listargate-aclug.cgi


[Prev in Thread] Current Thread [Next in Thread]