62

I'm doing an assignment where we have to read a series of strings from a file into an array. I have to call a cipher algorithm on the array (cipher transposes 2D arrays). So, at first I put all the information from the file into a 2D array, but I had a lot of trouble with conflicting types in the rest of my code (specifically trying to set char[] to char*). So, I decided to switch to an array of pointers, which made everything a lot easier in most of my code.

But now I need to convert char* to char[] and back again, but I can't figure it out. I haven't been able to find anything on google. I'm starting to wonder if it's even possible.

tparf
  • 657
  • 1
  • 6
  • 8

5 Answers5

129

It sounds like you're confused between pointers and arrays. Pointers and arrays (in this case char * and char []) are not the same thing.

  • An array char a[SIZE] says that the value at the location of a is an array of length SIZE
  • A pointer char *a; says that the value at the location of a is a pointer to a char. This can be combined with pointer arithmetic to behave like an array (eg, a[10] is 10 entries past wherever a points)

In memory, it looks like this (example taken from the FAQ):

 char a[] = "hello";  // array

   +---+---+---+---+---+---+
a: | h | e | l | l | o |\0 |
   +---+---+---+---+---+---+

 char *p = "world"; // pointer

   +-----+     +---+---+---+---+---+---+
p: |  *======> | w | o | r | l | d |\0 |
   +-----+     +---+---+---+---+---+---+

It's easy to be confused about the difference between pointers and arrays, because in many cases, an array reference "decays" to a pointer to it's first element. This means that in many cases (such as when passed to a function call) arrays become pointers. If you'd like to know more, this section of the C FAQ describes the differences in detail.

One major practical difference is that the compiler knows how long an array is. Using the examples above:

char a[] = "hello";  
char *p =  "world";  

sizeof(a); // 6 - one byte for each character in the string,
           // one for the '\0' terminator
sizeof(p); // whatever the size of the pointer is
           // probably 4 or 8 on most machines (depending on whether it's a 
           // 32 or 64 bit machine)

Without seeing your code, it's hard to recommend the best course of action, but I suspect changing to use pointers everywhere will solve the problems you're currently having. Take note that now:

  • You will need to initialise memory wherever the arrays used to be. Eg, char a[10]; will become char *a = malloc(10 * sizeof(char));, followed by a check that a != NULL. Note that you don't actually need to say sizeof(char) in this case, because sizeof(char) is defined to be 1. I left it in for completeness.

  • Anywhere you previously had sizeof(a) for array length will need to be replaced by the length of the memory you allocated (if you're using strings, you could use strlen(), which counts up to the '\0').

  • You will need a make a corresponding call to free() for each call to malloc(). This tells the computer you are done using the memory you asked for with malloc(). If your pointer is a, just write free(a); at a point in the code where you know you no longer need whatever a points to.

As another answer pointed out, if you want to get the address of the start of an array, you can use:

char* p = &a[0] 

You can read this as "char pointer p becomes the address of element [0] of a".

Timothy Jones
  • 21,495
  • 6
  • 60
  • 90
  • 1
    In the last example, can't `char *p = &a[0]` be simplified to just `char *p = &a` ? – thom_nic Jun 25 '15 at 18:17
  • 1
    @thom_nic: No, because `&a` has the type `char (*)[6]`, ie, a pointer to an array of six characters. This isn't the same as `char *`, so you'll get a warning. However, you can say `char *p = a;`, because an array reference can [decay into a pointer to its first element](http://c-faq.com/aryptr/aryptrequiv.html). I used the longer form here, because it better illustrates what's happening. – Timothy Jones Jun 26 '15 at 01:04
  • Ah, I see that the words I used on the second last line could have been confusing. I've edited the answer. – Timothy Jones Jun 26 '15 at 01:11
  • 1
    I would also add that in case of `char *a`, if `a` is uninitialized or points to a string literal, like `char *a = "hello"`, then `a[0]` or `a[1]` would be a valid read, but any attempt to write to what `a` points to would not be valid, resulting in segmentation fault. – Alexander Strakhov Mar 05 '19 at 00:27
22

If you have char[] c then you can do char* d = &c[0] and access element c[1] by doing *(d+1), etc.

dave
  • 12,406
  • 10
  • 42
  • 59
3

You don't need to declare them as arrays if you want to use use them as pointers. You can simply reference pointers as if they were multi-dimensional arrays. Just create it as a pointer to a pointer and use malloc:

int i;
int M=30, N=25;
int ** buf;
buf = (int**) malloc(M * sizeof(int*));
for(i=0;i<M;i++)
    buf[i] = (int*) malloc(N * sizeof(int));

and then you can reference buf[3][5] or whatever.

jcai
  • 3,448
  • 3
  • 21
  • 36
  • 3
    Don't cast the result of `malloc()`. – Keith Thompson Mar 09 '12 at 02:26
  • It's necessary because `malloc()` returns a `void *`, which needs to be cast to an `int *` to be stored in `buf`. – jcai Mar 09 '12 at 02:37
  • 6
    No, the cast is not necessary. In C, an expression of type `void*` can be implicitly converted to any pointer-to-object (or pointer-to-incomplete) type. See question 7.7b of the [comp.lang.c FAQ](http://c-faq.com/) and section 6.5.16.1 of the [C standard](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf). (C++ has different rules, which would be relevant if we were discussing C++.) – Keith Thompson Mar 09 '12 at 02:40
1

None of the above worked for me except strtok

#include <string.h>

Then use strtok

char some[] = "some string";
char *p = strtok(some, "");

strtok is used to split strings. But you can see that I split it on nothing ""

Now you have a pointer.

surge10
  • 622
  • 6
  • 18
-10

Well, I'm not sure to understand your question...

In C, Char[] and Char* are the same thing.

Edit : thanks for this interesting link.

  • 3
    I'm afraid that's not true - [pointers and arrays are not the same thing in C](http://www.lysator.liu.se/c/c-faq/c-2.html) – Timothy Jones Mar 09 '12 at 02:13
  • @TimothyJones: A better link for the FAQ is http://c-faq.com/. And of course you're 100% correct: arrays and pointers are *not* the same thing. (And it's spelled `char`, not `Char`; it matters.) – Keith Thompson Mar 09 '12 at 02:27
  • 1
    Probably more proper to say "behave similarly in most circumstances". – Hot Licks Mar 09 '12 at 02:27
  • 2
    @HotLicks: No, that's not right either. A pointer contains the address of some object. An array contains a sequence of objects. Not only are they not the same thing, they're not even similar. Arrays are typically *accessed* via pointers to their members. – Keith Thompson Mar 09 '12 at 02:28
  • @KeithThompson: Oops, I hadn't noticed the URL. I can't edit my comment any more though :( Here is the better direct link: http://c-faq.com/aryptr/aryptr2.html – Timothy Jones Mar 09 '12 at 02:32