Home > OS >  addressing with pointer in c languagge
addressing with pointer in c languagge

Time:11-06

I'm studying pointers in C language with Ted Jensen's "A TUTORIAL ON POINTERS AND ARRAYS IN C" manual. It's a very prickly argument.

Question 1. I have come to program 3.1 and would like a clarification. This is the program:

#include <stdio.h> 
char strA[80] = "A string to be used for demonstration purposes";
char strB[80]; 
int main(void) { 
char *pA; 
char *pB;
puts(strA); 
pA = strA; 
puts(pA); 
pB = strB;
putchar('\n');
while(*pA != '\0')
{ 
*pB   = *pA  ; 
} 
*pB = '\0';
puts(strB);
return 0; 
}

Regarding the line pA = strA;, the book says "We then [point] the pointer pA at strA. That is, by means of the assignment statement we copy the address of strA [0] into our variable pA", which is what I don't understand.

To copy the address of strA[0] into our variable pA via the assignment declaration, shouldn't we write pA = & strA?

Question 2. The expression c = * p; increases the value of p or the address of p?

Does the indirection operator (*) not indicate the value of the pointed variable?

CodePudding user response:

To copy the address of strA [0] into our variable pA via the assignment declaration, shouldn't we write pA = & strA?

&strA is the address of strA. &strA[0] is the address of strA[0]. These are the “same” in the sense they point to the same place in memory, but they have different types, and the compiler would complain if we wrote pA = &strA when the type of pA is a pointer to the type of the elements of strA.

When we write pA = strA, the array strA is automatically converted to a pointer to its first element, so pA = strA is equivalent to pA = &strA[0].

Question 2: the expression c = * p; increases the value of p or the address of p?

The C grammar organizes this as c = *( p);, and p increases the value of p. If p is a pointer, it increases the value of that pointer. The * operator uses the increased value.

Be careful about speaking of the address of a pointer. The value of the pointer is an address, but you should not say that is the address of the pointer. The pointer is itself an object in memory, and so it has an address in memory where its value is stored. The address where a pointer is stored is different from the address stored in it. The “address of a pointer” is the address where the pointer is stored, not the value of the pointer.

CodePudding user response:

It's simply because strA, which is char array, is a pointer. An array's "value" is actually nothing more than the address of the first element of array.

When you assign address of primitive data type(int, char, etc..), you should assign it in the way you described.

int x;
int *pA;
pA = &x;

When you assign address of pointer data type(array, etc..), you should assign it without & operator, since the value is in itself the address.

int x[10];
int* pA;
pA = x;

Original code

#include <stdio.h>
char strA[80] = "A string to be used for demonstration purposes";
char strB[80];
int main(void)
{
    char *pA; /* a pointer to type character */
    char *pB; /* another pointer to type character */
    puts(strA); /* show string A */
    pA = strA; /* point pA at string A */
    puts(pA); /* show what pA is pointing to */
    pB = strB; /* point pB at string B */
    putchar('\n'); /* move down one line on the screen */
    while(*pA != '\0') /* line A (see text) */
    {
        *pB   = *pA  ; /* line B (see text) */
    }
    *pB = '\0'; /* line C (see text) */
    puts(strB); /* show strB on screen */
    return 0;
}

CodePudding user response:

In C, when you write :

char strA[80];

Memory is allocated for your table. This is an example for you to try and visualize what it looks like.

[0] 1st Element [1] 2nd Element [2] 3rd Element [....] .... [n] nth Element
0000 0001 0002 0003 n

strA is a pointer to the address where your table starts in the memory (0000 in our example), which is the same as the address of its first element strA[0].

So when you write

pA = strA

you are actually copying the first element's address (0000 in our example) to pA

CodePudding user response:

To copy the address of strA [0] into our variable pA via the assignment declaration, shouldn't we write pA = & strA?

Arrays are weird and don't behave like other types.

The expression strA "decays" from type "N-element array of char" to "pointer to char", and the value of the expression is the address of the first element. This "decay" doesn't happen when the array expression is the operand of the sizeof or unary & operators, so the expression &strA has type "pointer to N-element array of char", or char (*)[N], which is not the same as char *. The address value is the same (the address of an array is the same as the address of its first element), but the types are different.

Assuming the declarations

char str[N]; // for some size N
char *p;

when you write

p = str; // char * = char *

the expression str has type "N-element array of char"; however, since str is not the operand of the sizeof or unary & operators, it "decays" to type char * and evaluates to the address of the first element. It’s equivalent to writing

p = &str[0];  // char * = char *

There is a reason for this - C was derived from an earlier language named B, and in B array types had a dedicated pointer to the first element - when you declared an array in B like

auto a[N];

what you got in memory was

    --- 
a: |   | ------- 
    ---         |   
    ...         |
    ---         |
   |   | a[0] <- 
    --- 
   |   | a[1]
    --- 
    ...

and the array subscript operation a[i] was defined as *(a i) - given the starting address a, offset i elements from that address and dereference the result.

When he was designing C, Ritchie wanted to keep B's array behavior, but he didn't want to keep the explicit pointer that behavior required. When you declare an array in C like

int a[N];

what you get in memory is

    --- 
a: |   | a[0]
    ---   
   |   | a[1]
    --- 
    ...

Instead of setting aside space for an explicit pointer to the first element, the compiler replaces any occurrences of the expression a with a pointer to a[0]. So a[i] is still defined as *(a i). Unfortunately, this means that arrays lose their "array-ness" under most circumstances and most of the time what you're dealing with is a pointer.

Question 2: the expression c = * p; increases the value of p or the address of p?

This gets a little complicated. To answer as asked, it increases the value of p - it sets p to point to the next object in a sequence. This is probably better explained with a concrete example.

Assume the following declarations:

char str[] = "foo";
char *p = str;

then the following are true:

      --- 
str: |'f'| str[0]   <--- p
      --- 
     |'o'| str[1]   <--- p   1
      --- 
     |'o'| str[2]   <--- p   2
      --- 
     | 0 | str[3]   <--- p   3
      --- 

 p == &str[0]             // char * == char *
*p ==  str[0] == 'f'      // char   == char   == char

  p   1  == &str[1]
*(p   1) ==  str[1] == 'o'

  p   2  == &str[2]
*(p   2) ==  str[2] == 'o'

The result of the expression p 1 is a pointer to str[1], the result of the expression p 2 is a pointer to str[2], etc.

c = * p; is roughly equivalent to writing

tmp = p   1;
c = *tmp;
p = p   1;

with the caveat that the updates to c and p can happen in any order - they may even be evaluated simultaneously (either interleaved or in parallel).

In this case, it means we assign the value of *(p 1) ('o') to c, and update p to point to str[1], leaving us with this:

      --- 
str: |'f'| str[0]   
      --- 
     |'o'| str[1]   <--- p
      --- 
     |'o'| str[2]   <--- p   1
      --- 
     | 0 | str[3]   <--- p   2
      --- 

 p == &str[1]
*p ==  str[1] == 'o'

  p   1  == &str[2]
*(p   1) ==  str[2] == 'o'

  p   2  == &str[3]
*(p   2) ==  str[3] == 0
  •  Tags:  
  • c
  • Related