Jason M.
Jason M.

Reputation: 702

referencing an index value of a character in a pointer string in c

Suppose I have something like this

int strLen;

printf("Please enter a number: ");
scanf("%d", &strLen);

char *myString;

myString = (char*) malloc(strLen*sizeof(char));

then you fill string with something like "Hello World!" but now I want to just print out "World!" Since my string is just a pointer reference, I can't call it out by indexes ie.

for(int i=6;i<strLen;i++)
{
    printf("%s", myString[i]);
}
// THIS IS AN INCORRECT WAY TO DO THIS

How could I refer to a specific character or even pass the array onto another function of the program if all I have is the array base pointer? Can I ever get the full functionality as if I declared it as a static array before compile time?

Upvotes: 0

Views: 16651

Answers (3)

John Bode
John Bode

Reputation: 123448

How could I refer to a specific character or even pass the array onto another function of the program if all I have is the array base pointer?

Several things to remember:

  • Except when it is the operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be replaced with ("decay to") an expression of type "pointer to T" whose value is the address of the first element of the array;

  • In the context of a function parameter declaration, T a[N] and T a[] are identical to T *a (IOW, a will be declared as a pointer to T, not an array of T - note that this is only true for function parameter declarations);

  • The subscript operation a[i] is defined as *(a + i) - start with a base address specified by the pointer expression a, offset by i elements (not bytes), and dereference the result;

  • In C, you do not need to cast the result of malloc (or calloc or realloc), since it returns a value of type void *, which may be assigned to any other object pointer type. Adding the cast may suppress a useful diagnostic if you forget to include stdlib.h or otherwise don't have a prototype in scope. Note that this is not true for C++ - a cast is required there, but if you're writing C++ you should be using new instead of malloc anyway.

This is a long-winded way of saying that, in many contexts, array expressions and pointer expressions can be treated the same way. Taking printf as an example:

int main(void)
{
  char foo[] = "This is a test";
  char *bar = foo;

  printf("%s\n", foo);
  printf("%s\n", &foo[0]);
  printf("%s\n", bar);

  return 0;
}

printf expects the argument corresponding to %s to have type char *, or "pointer to char", not "array of char". The three printf calls above are all equivalent. In the first call, foo is an array expression with type "15-element array of char". By the first rule mentioned above, it will be replaced with an expression of type "pointer to char" whose value is the address of the first element. The second and third calls pass the pointer value directly, just using different expressions to accomplish the same effect.

As far as printf is concerned, all three expressions yield the same result -- the address of the first element of a sequence of char values, terminated by 0.

What does this mean for your code? Well, for one thing, you can use the subscript operator on mystring as though it were an array type:

printf("%s\n", &mystring[6]); // prints "World!"

Note that the subscript operator [] has higher precedence than the unary & operator, so the above is interpreted as &(mystring[6]) - we subscript into mystring and then take the address of the result.

You can pass mystring to any function that you would pass an array of char to:

void foo(char str[]) // identical to char *str
{
  // do something with str
}
...
int main(void)
{
  char str[] = "Hello, World!";
  char *mystr = malloc(strlen(str) + 1); // note no cast
  strcpy(mystr, str);
  foo(str);
  foo(mystr);
  ...
}

Again, as far as the function foo is concerned, its argument is type char *, not array of char. The expression str decays to a pointer value, and mystr is a pointer value to begin with.

Upvotes: 4

paulsm4
paulsm4

Reputation: 121649

A couple of things:

1) Allow for the null terminator in your "malloc()":

int strLen;
...
char *myString = (char*) malloc(strLen+1);

2) The "sizeof(char)" is kind of duplicate redundant. No harm - but no purpose, either. So I omitted it.

3) This is wrong:

for(int i=6;i<strLen;i++)
{
  printf("%s", myString[i]);
}

4) This is better:

for(int i=6;i<strLen;i++)
{
  printf("%c", myString[i]);
}

Upvotes: 1

Michael Chinen
Michael Chinen

Reputation: 18697

You can take the address of the character at a certain array index.

So, try this if you just want to print out 'world!':

#include <stdio.h>

int main(int a, char** b)
{
   int strLen;

   char *myString;

   myString = "hello world!";

   printf("%s", &myString[6]);

   return 0;
}

Upvotes: 0

Related Questions