Вы находитесь на странице: 1из 20

Intermediate C Workshop Pointers

By FCG Team

Version: <1.3> Date: < 23/10/2006>

Pointers Basics Pointer holds address of a variable.


int x = 10; int *p = &x; printf(&x=%p, p=%p, x=%d, *p=%d\n, &x, p, x, *p); Output: &x=0x22cce4, p=0x22cce4, x=10, *p=10

&X

*p
10 0x22CCE4

0x22CCE4 0x22CCE8
&p

Since & operator is available, why do we need a pointer ?


& cannot be used as a lvalue &x = p; /* this is not a legal statement */

Wipro confidential

Pointers Basics Even const pointers do not have lvalue


int * const p = x; p = p + 1; /* illegal statement */ const int *p = x; *p = 10; /* illegal statement */

Wipro confidential

Pointers Basics Pointer holds an address Needs to be initialized to legal address

*p 0x22CC00 0x22CC01 0x22CC02 0x22CC03 0x22CC04 0x22CC05

But, need not be always initialized as an address of a variable. Examples: char *p = Hello; int *ip = malloc(2 *sizeof(int)); *ip = 1; *(ip+1)=2;
p
&p

H e l l o \0

*(p+1)

*(p+5)

*ip
0x22EE00 0x22EE04

0x22CC00 0x22DD00

0x22DD00 0x22DD04

1 2

&ip

*(ip+1)

ip
Wipro confidential 4

Pointers Basics
Important points to remember
Constant Data

Hello string in this example will be in constant data segment Memory pointed by ip will be in heap p and ip will be present in stack if they are local variables. If they are global or static local variables, they will be present in data segment. To differentiate the various segments, each segment is shown in different color.
Stack if p and ip are local variables

*p *(p+1)

0x22CC00 0x22CC01 0x22CC02 0x22CC03 0x22CC04 0x22CC05

H e l l o \0

*(p+5)

0x22DD00

p
&p

0x22DD04

1 2

*ip
*(ip+1)

&ip

0x22EE00 0x22EE04

0x22CC00 0x22DD00

Heap

ip
Wipro confidential 5

Pointers Basics

Notes Note that addresses of variables which are present in the


heap or constant data segment when stored in local variables have their addresses stored in variables allocated on the stack. The heap and the data segment have a lifetime that spans across the life of the program. Therefore dynamically allocated memory, constant data and global variables have a life as long as that of the process. The scope of variables on the stack is limited to the function or block in which it is present. Typically all automatic variables are allocated on the stack. From a function, returning the address of a local variable, whose scope is not defined beyond the function will result in unpredictable behavior.

Wipro confidential

Pointers Basics

Size of a pointer variable Since a pointer stores an address, the size of the pointer

variable is the same as the size required to store an address (typically 4-bytes for all 32-bit architectures) Size of a pointer variable is the same, irrespective of the type it is pointing to.

Wipro confidential

Pointers Frequently done mistakes with pointers Frequent mistakes with pointers
p is not pointing to any legal address. This will cause segmentation fault.

Using an uninitialized pointer


char *p; strcpy(p, Hello);

Incorrect pointer arithmetic


typedef struct {
int day; int month; int year;

Adding sizeof(DATE), dp moves by sizeof(DATE) * sizeof(DATE)

} DATE, *DATEP; DATE a[2]= {{1,1,2006}, {1,1,2007}}; DATEP dp = a; dp = dp + sizeof(DATE);

Crossing the logical boundary.


char *p=Hello; strcat(p, World);

In some architectures, it is illegal to write into const data segment and can cause memory fault. Even if writing to const area is acceptable in some architectures, p is pointing to memory that has only 6 bytes. Adding World to it, would corrupt other data.

Wipro confidential

Pointers Basics Arrays and Pointers


char a[10]=Hello; char *str = a; printf(%s %s\n, a, str); printf(%c %c %c %c\n, a[1], str[1], 1[str], 1[a]); printf(%p %p %p %p\n, a, str, &a[1], str+1); Output:

Hello Hello eeee 0x22ccd0 0x22ccd0 0x22ccd1 0x22ccd1

Then, can pointers and arrays be interchangeably used?

Yes and No.

Wipro confidential

Pointers Basics

Arrays and Pointers


char a[10]=Hello; char *str = a; printf(%d %d %d\n, sizeof(a), sizeof(str), strlen(a));

Output: 10 4 5

Wipro confidential

10

Pointers Basics Double Dimension arrays and double pointers


main() { char a[5][10]={"One", "Two", "Three", "Four", "Five" }; char **str = a; char *b[5]={"One", "Two", "Three", "Four", "Five" }; char **str1 = b; printf("%d %d %d %d\n", sizeof(a), sizeof(str), sizeof(b), sizeof(str1)); printf("%p %p %p %p %p %p\n", a, str, &a[1], &str[1], &a[1][1], &str[1][1]); printf("%p %p %p %p %p %p\n", b, str1, &b[1], &str1[1], &b[1][1], &str1[1][1]); }

Output:
50 4 20 4 0x22cca0 0x22cca0 0x22ccaa 0x22cca4 0x22ccab 0x1 0x22cc60 0x22cc60 0x22cc64 0x22cc64 0x403005 0x403005

Wipro confidential

11

Pointers Basics
Double Dimension arrays and double pointers
a[1]: Second dimension size of a is 10 and hence 10 is added.

main() {

Str points to a pointer. &str[1] is str+1 and since size of a pointer is 4 bytes, str + 1 translates to 0x22cca0 + 4

20: because it is array of 5 pointers

char a[5][10]={"One", "Two", "Three", "Four", "Five" }; char **str = a; Add 1 to a[1] char *b[5]={"One", "Two", "Three", "Four", "Five" }; char **str1 = b; printf("%d %d %d %d\n", sizeof(a), sizeof(str), sizeof(b), sizeof(str1)); printf("%p %p %p %p %p %p\n", a, str, &a[1], &str[1], &a[1][1], &str[1][1]); printf("%p %p %p %p %p %p\n", b, str1, &b[1], &str1[1], &b[1][1], &str1[1][1]); &str[1][1] translates to
&(*(*(str+4) + 1)), i.e &(*(*(0x22cca4) + 1))). This is equal to &(*(0 + 1)) and is equal to 1 and str[1][1] will be a junk value

Output:
50 4 20 4 0x22cca0 0x22cca0 0x22ccaa 0x22cca4 0x22ccab 0x1 0x22cc60 0x22cc60 0x22cc64 0x22cc64 0x403005 0x403005

Wipro confidential

12

Pointer Basics

&str[0][0]

a &str1[0][0] b

0 1 2 3 4 5
0x22cca0 0x22ccaa . . .

6 7 8 9
0x22cc60 0x22cc64 . . .

a[0] O n e \0 a[1] T w o \0 a[2] T h r e e \0 a[3] F o u r \0 a[4] F i v e \0

b[0] b[1] b[2] b[3] b[4]

One\0 Two\0 Three\0 Four\0 Five\0

&str[1][1] translates to &(*(*(str+4byte) + 1)), i.e &(*(*(0x22cca4) + 1))). This is equal to &(*(0 + 1)) and is equal to 1. So str[1][1] will be a junk value

str1[1][0]= str1[1]=*(str1 + 4byte) *(*(str1+4bytes)+0) =T str1[1][1] Wipro confidential

13

Pointer Basics

Junk\0 0 1 2 3 4 5 6 7 8 9

a[0] O n e \0 a[1] T w o \0 a[2] T h r e e \0 a[3] F o u r \0 a[4] F i v e \0 char *temp = junk; a[0]=temp;

b[0] b[1] b[2] b[3] b[4]

One\0 Two\0 Three\0 Four\0 Five\0

char *temp= junk; b[2] = temp;


Wipro confidential 14

Pointers Arithmetic & Casting


typedef struct { int day; int month; int year; } Date;

ef be ad de ee ff

c0

00

d e

1f ca

af

de

de

ca

all
cp+1 sp+1 ip+1cp+5 sp+3 ip+2 dp+1 ip + 3 dp+2 ip + 6 sp + 16 cp + 24

int abc=0xdeadbeef; int def=0xc0ffee; char ghi[6]=abcde; int jkl = 0xdeafca1f; short mno = 0xcade; Date pqr = { 1, 1, 2006 }; main() { int *ip = &abc; short *sp = (short *)&abc; char *cp = (char *) &abc; Date *dp = (Date *) &abc; .. } Note: Little endian architecture assumed

sp + 8 cp + 12

When a pointer is incremented by 1, depending upon the type, number of bytes moved will differ. When casting from one type to another Take care of alignment issues (SIGBUS) Keep in mind that number of bytes that will move for every increment/decrement will change.
Wipro confidential 15

Pointers Function pointers Pointers can point to functions as well in addition to variables.

Declaration example: int (*f1)(int,char **) -> Pointer to a function that returns int and takes one integer and one char double pointer as arguments. Assignment example: f1=main;

A pointer variable that points to a function contains the address of the first executable instruction of the function.

Wipro confidential

16

Pointers Function pointers


All the pointer arithmetic, casting, etc is applicable to function pointers also. void * fast_algo(int size); void * mid_algo(int size); void * slow_algo(int size); typedef enum { HIGHSPEED_HIGHMEM, MIDSPEED_MIDMEM, LOWSPEED_LOWMEM } ALGO_CLASS; ALGO_CLASS x; void* (*MemAllocAlgo[3])(int) = { fast_algo, mid_algo, slow_algo}; void* (*MyAlloc)(int); void AssignAllocator(ALGO_CLASS user_choice) { void* (**TempMyAlloc)(int); TempMyAlloc = MemAllocAlgo; MyAlloc = MemAllocAlgo[user_choice]; /* Alternate1: MyAlloc= TempMyAlloc[user_choice] Alternate 2: MyAlloc = *(TempMyAlloc + user_choice) */ }
Wipro confidential 17

Volatile pointers

Volatile keyword informs compiler that optimizations must be disabled for that variable. The following code has a problem. Compiler will not generate code for disabling interrupt.

#define BASE_ADDRESS 0x80808000 #define INTERRUPT_REGISTER_OFFSET 0x10 CriticalSection() { int *intr_reg = (BASE_ADDRESS + INTERRUPT_REGISTER_OFFSET); *(intr_reg) = 1; /* disables interrupt */ /* critical code, interrupt must be disabled here */ . . /* critical code is executed, interrupt can be enabled here */ *(intr_reg) = 0; /* enables interrupt */ } The problem can be solved simply by defining intr_reg as volatile: volatile int *intr_reg = (BASE_ADDRESS + INTERRUPT_REGISTER_OFFSET);

Wipro confidential

18

Think about this Volatile & Constant together

Can constant and volatile be used together during a declaration? Example:

volatile int * const p = 0xc8000000;

Wipro confidential

19

Thank you.

Information contained and transmitted by this presentation is proprietary to Wipro Limited and is intended for use only by the individual or entity to which it is addressed, and contains information that is privileged, confidential or exempt from disclosure under applicable law.

Wipro confidential

20

Вам также может понравиться