NO

Author Topic: Pointers to char arrays  (Read 5511 times)

Cnoob

  • Guest
Pointers to char arrays
« on: April 14, 2015, 03:24:45 AM »
Hi

First post and greetings to all.
Busy learning C and have downloaded gcc and also Pelles.

I do have a question regarding on how to relate a pointer to a position in a char array.
Let's say I use strstr() to look for the existence of a string within another string.
Assuming that a match is found, strstr() will return a pointer which I assume is the address in memory of the array of the first instance of the occurrence
but how do I relate this to a offset within the actual string?

Sorry if it's a stupid question but still trying to wrap my mind around pointers.

Thank you in advance.

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2096
Re: Pointers to char arrays
« Reply #1 on: April 14, 2015, 09:50:41 AM »
An index is the position of an element in an array. In your case it is the position of the first char from which starts the substring you found in array of characters.
To get a pointer to an element of an array you can use two ways:
Code: [Select]
char MyString[]="My string!";
char *p;
//If you want the part "string!" of the string you have to refer to the 3rd element: index 3
p = &Mystring[3];  //Get the address of 3rd element using the '&' operator
//or
p = MyString + 3;  //Using the pointers arithmetic
Both systems are equivalent, but the second method opens a way to connect element address and index in a C array. This is normally referred as pointers arithmetic. In C if you add a vallue to a pointer to an array the compiler automatically fix the things to produce a correct pointer to the selected element.
Consider the case of an array of integers, an integer occupy 4 bytes in memory, so if first element is at the address 1000 (for sake of simplicity we use a small and decimal value), the second element will be at address 1004. When we write:
Code: [Select]
int aInt[10];
int *p = aInt + 1;  //This will be translated by compiler in p = aInt + (1 * sizeof(int));
Now if you want back the index from a pointer simply compute the difference:
Code: [Select]
int aInt[10];
int *p = aInt + 5;     //Get the address of the 5th element...
int index = p - aInt;  //index will contain 5
You can have a look here for a better understanding, and here. You can collect major info googling for "pointers arithmetic".
« Last Edit: April 14, 2015, 10:07:03 AM by frankie »
It is better to be hated for what you are than to be loved for what you are not. - Andre Gide

Snowman

  • Guest
Re: Pointers to char arrays
« Reply #2 on: April 14, 2015, 10:17:09 AM »
Sorry if it's a stupid question but still trying to wrap my mind around pointers.

My post is just to give a small clarification on pointers (in case you need it).
  • Pointers are nothing more than variables which store a memory address.
  • The type of the pointer hints what kind of data is stored at that memory address.
  • This hint is important because different types use a different number of bytes, e.g. char uses one byte, float uses four bytes.
Because the type of a pointer is just a hint, you may have pointers void. But you can't dereference them ("dereference" is a fancy word meaning "retrieve the data located at the address they're storing") because the type void gives no hint what kind of data they're pointing at. So the computer doesn't know how many bytes to retrieve, starting from that address.

This is why you need to cast void pointers.

Code: [Select]
#include <stdio.h>

int main(void)
{
    int i=5;
    void *vi = &i; // void pointer to i (stores address of i)

    printf("address: %p data: %d\n", vi, *(int *)vi);
    // *(int *)vi does two things:
    // 1. casts vi from "pointer to void" to "pointer to int"
    // 2. uses the dereference operator * to retrieve the data
}

Try not to confuse the asterisk (*) when used to declare a pointer with when it is a dereference operator.

void pointers are useful because they allow you to write functions that accept any kind of pointer.
An example from the C library is memcpy() the declaration of which looks like this:

Code: [Select]
void* memcpy( void *dest, const void *src, size_t count );
http://en.cppreference.com/w/c/string/byte/memcpy

Cnoob

  • Guest
Re: Pointers to char arrays
« Reply #3 on: April 14, 2015, 11:05:31 AM »
Thank you frankie and Snowman for taking the time to respond.

@frankie

So pointers are just that, pointers to an array so once I have the location in memory the array starts at, it's a simple matter to compute any offset within that array using pointer arithmetic.
So I get the start of an array (let's say 1000) and the result from strstr() is 1004, then I know that the first occurrence is in the 5th byte of the array.
Hope I got that right.
BTW, those links you posted are great.

@Snowman

Thanks for the info on the different uses of the asterisk (declaration and deference).
I never thought about not being able to access an array of type void, but it makes perfect sense, as you say, how many bytes to retrieve.

I'm off to do lot's of practicing.


Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2096
Re: Pointers to char arrays
« Reply #4 on: April 14, 2015, 01:41:26 PM »
So pointers are just that, pointers to an array so once I have the location in memory the array starts at, it's a simple matter to compute any offset within that array using pointer arithmetic.
Wait, pointers are pointers to objects: integers, chars, floats, structures, etc. But an array name is the pointer to its first element. So it's true the way round  ::)
Now we touch one of the obscure features of C: an array and a pointer of the same type share the same properties and methods, even if the assembly code to access data is completely different! Another difference is that you can get the address of a pointer, which is a variable holding the address of another variable, but you cannot get the address of an array.
I.e.:
Code: [Select]
int aInt[10]={0,1,2,3,4,5,6,7,8,9};
int *p;
int **pp;    //pp is a pointer to a pointer of int's. It can hold the address of p that is a pointer of int's

pp = &p;        //No errors
pp = &aInt;    //Error!

printf("%d %d %d %p\n", aInt[1], *aInt, *(aInt+3], aInt);
p = aInt;
printf("%d %d %d %p\n", p[1], *p, *(p+3), p);
So I get the start of an array (let's say 1000) and the result from strstr() is 1004, then I know that the first occurrence is in the 5th byte of the array.
Hope I got that right.
BTW, those links you posted are great.
Yes you got it right.
It is better to be hated for what you are than to be loved for what you are not. - Andre Gide

Cnoob

  • Guest
Re: Pointers to char arrays
« Reply #5 on: April 14, 2015, 07:04:59 PM »
Wait, pointers are pointers to objects: integers, chars, floats, structures, etc.

OK got that, is every variable then in C an array or do they have to be explicitly be declared as an array before I can access different locations of that array.
By this I mean let's say we have an int var = 0x1234, not explicitly declared as an array, can I still access any of the 4 bytes that are used for the int?
Similar to assembler where we can load a 32 bit value in EAX but then manipulate say the bottom 16 bits with AX or AH, AL for 8 bits?

But an array name is the pointer to its first element. So it's true the way round  ::)

As in ThisArray[0] ?

Now we touch one of the obscure features of C: an array and a pointer of the same type share the same properties and methods, even if the assembly code to access data is completely different! Another difference is that you can get the address of a pointer, which is a variable holding the address of another variable, but you cannot get the address of an array.

So a pointer at say address 1000 contains a value of 5000, this value is then the address of the variable in the array ?

Will also try the code you posted.

What I found that has also helped to clear a bit of my confusion is this code snippet:

Code: [Select]
struct {
    char a;
    char b;
    char c;
    char d;
} mystruct;

mystruct.a = 'r';
mystruct.b = 's';
mystruct.c = 't';
mystruct.d = 'u';

char* my_pointer;
my_pointer = &mystruct.b;

printf("Start: my_pointer = %c\n", *my_pointer);
my_pointer++;
printf("After: my_pointer = %c\n", *my_pointer);
my_pointer = &mystruct.a;
printf("Then: my_pointer = %c\n", *my_pointer);
my_pointer = my_pointer + 3;
printf("End: my_pointer = %c\n", *my_pointer);

It's about half way down the page here:
http://stackoverflow.com/questions/5727/what-are-the-barriers-to-understanding-pointers-and-what-can-be-done-to-overcome

I understand the concept of addresses and memory, it's just getting to grips with the C syntax.

Thank you very much for your help.
« Last Edit: April 14, 2015, 07:07:26 PM by Cnoob »

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2096
Re: Pointers to char arrays
« Reply #6 on: April 14, 2015, 07:32:42 PM »
You got almost everything good, only maybe a residual point when you talk to access the 4 byte of an int with a pointer to the int: yes you can if your pointer is declared as a pointer to 1 byte variable, typically a pointer to char, not if you declared it as a pointer to int because the pointers arithmetic will change all your computations to steps of same dimension of the pointed variable.
Code: [Select]
int MyInt=0x1234;
char *p = (char *)&MyInt;    //We have to cast it to a char pointer
for (int i=0; i<sizeof(int); i++)
  printf("Byte %d = %d\n", i, p[i]);
It is better to be hated for what you are than to be loved for what you are not. - Andre Gide

Cnoob

  • Guest
Re: Pointers to char arrays
« Reply #7 on: April 14, 2015, 08:03:45 PM »
yes you can if your pointer is declared as a pointer to 1 byte variable, typically a pointer to char, not if you declared it as a pointer to int because the pointers arithmetic will change all your computations to steps of same dimension of the pointed variable.

Understood, thanks.

Offline jj2007

  • Member
  • *
  • Posts: 536
Re: Pointers to char arrays
« Reply #8 on: April 15, 2015, 02:47:19 AM »
p[ i ] is the equivalent to eax in movzx eax, byte ptr [esi]

(I see you are coming from assembler - welcome in the club  ;) )

Cnoob

  • Guest
Re: Pointers to char arrays
« Reply #9 on: April 15, 2015, 10:21:12 AM »
Hi jj2007

Quote
p[ i ] is the equivalent to eax in movzx eax, byte ptr [esi]

Yes, I see what you mean, so as to move one character from a string pointed to by esi.

I've thought of using inline assembler in C but the syntax used for constraints and the clobber list is very unintuitive and I'm trying to learn C anyway so in a sense it would be "cheating".  :D


EDIT:

I was curious so decided to try some assembler in Pelles thinking that I would need to use the same outrageous syntax as per gcc (hence my comment above).
However I was very pleasantly surprised at just how easy it is to include assembler in Pelles.

Code: [Select]
__asm{
........
   }

Fantastic.
Developers of gcc, take note.


« Last Edit: April 15, 2015, 01:57:21 PM by Cnoob »