-5

I'm trying to create and store a char* array.

So, first I tried this:

int main() {
    char* values[3];
    values[0] = "Hello";
    values[1] = "Mew meww";
    values[2] = "Miau miau =3";

    for(int i=0; i<sizeof(values); i++)
        printf("%s", values[i]);
}

it works with this OUTPUT:

Hello Mew Mew Miau miau =3

If i try:

printf("%s", "Tamaño del diccionario: ");
int tam;
scanf("%i", &tam);
char* dic[tam];
Word words[tam];

    for(int i=0; i<tam; i++)
{
    printf("Palabra %d: ",(i+1));
    scanf("%32s", &dic[i]);
}

        for(int i=0; i<tam; i++)
{
    printf("%s",dic[i]);
    printf("\n");
}

Show non-legible stuff like "0xassdfsdf"

What can I do to store it right in memory?

c_str
  • 369
  • 1
  • 4
  • 14
  • `sizeof(values)` --> `sizeof(values)/sizeof(*values)` – BLUEPIXY Jul 27 '14 at 00:44
  • values is an array of three pointers. sizeof(values) is the number of bytes that values takes up. Since it's an array of three pointers, assuming a pointer is four bytes, sizeof(values) = 3 * 4 = 12 bytes. – Eric Jul 27 '14 at 00:46
  • and for the second problem you need to allocate storage for the user strings (ie. not just an array of initialized pointers). – SleuthEye Jul 27 '14 at 00:46
  • No space is reserved for the elements of `dic`, you're writing to arbitrary memory addresses. – mafso Jul 27 '14 at 00:47
  • Yes! @BLUEPIXY I read it in here: http://stackoverflow.com/questions/4108313/how-do-i-find-the-length-of-an-array – c_str Jul 27 '14 at 00:48
  • `scanf("%32s", &dic[i]);` --> `scanf("%32s", dic[i]);` and pointer should point ensured memory. e.g `dic[i] = malloc(33);` – BLUEPIXY Jul 27 '14 at 00:49
  • So I have to make a new Array[] for my array? @mafso – c_str Jul 27 '14 at 00:49
  • @BLUEPIXY Yes, I tried it first! But my program crashes when I don't use &dic[0] :c – c_str Jul 27 '14 at 00:50
  • possible duplicate of [C sizeof char\* array](http://stackoverflow.com/questions/1559925/c-sizeof-char-array) – Deduplicator Jul 27 '14 at 00:52
  • @Deduplicator I asked for STORING. Not mainly get the size of an array. Please, READ the full question. – c_str Jul 27 '14 at 00:53
  • Well, you have multiple questions. Restrict yourself to the first one (as is proper), and it's a duplicate. – Deduplicator Jul 27 '14 at 00:54
  • @Zoditu _crashes when I don't use &dic[0]_ test run my post code. – BLUEPIXY Jul 27 '14 at 00:56
  • 1
    @sharth the problem is that almost none of you know to read. I never asked for sizeof(). I just mentioned "Don't know why this happens". If you were a prepared person and would have read the full question and title, would have understood it. But just two persons from all over here got it right. BLUE and Alexander in answers didn't even mentiones sizeof because they knew what I was asking. You all got the "easy" way lol – c_str Jul 27 '14 at 01:16

3 Answers3

3
#include <stdio.h>
#include <stdlib.h>

int main(){
    char* values[3];
    values[0] = "Hello";
    values[1] = "Mew meww";
    values[2] = "Miau miau =3";

    for(int i=0; i<sizeof(values)/sizeof(*values); i++)
        printf("%s\n", values[i]);

    printf("%s", "Size for dictionary: ");
    int tam;
    scanf("%i", &tam);
    char *dic[tam];

    for(int i=0; i<tam; i++){
        printf("Palabra %d: ",(i+1));
        dic[i] = malloc(33);
        scanf("%32s", dic[i]);
    }
    for(int i=0; i<tam; i++){
        printf("%s\n", dic[i]);
        free(dic[i]);
    }

    return 0;
}
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70
2

One problem is

scanf("%32s", &dic[i]);

which should be

scanf("%32s", dic[i]);

because the array contains pointers to storage, not storage itself, and what you should pass to scanf is this pointer. Indeed, a char* is just a 4-byte pointer. The array char* dic[tam] contains some such pointers, so that dic[0] is a 4-byte pointer to char, and &dic[0] is the address of this pointer. Then your

scanf("%32s", &dic[i]);

just overwrites this pointer plus corrupts memory after it.

Another problem is that you do not initialize the array, so it does not point to any storage.

char* dic[tam];

here the array contains pointers to random places in memory.

scanf("%32s", &dic[i]);

most probably this fails at all. So in your printf you print pointers to random places in memory.

A (bad) solution is:

for(int i=0; i<tam; i++)
{
    printf("Palabra %d: ",(i+1));

    dic[i] = new char [1000]; // here you assign it some storage

    scanf("%32s", dic[i]); // NOT &dic[i]
}

or (slightly better)

for(int i=0; i<tam; i++)
{
    printf("Palabra %d: ",(i+1));

    char buffer [1000]; // temporal storage arguably large enough

    scanf("%32s", buffer);

    dic[i] = new char [strlen (buffer) + 1]; // storage of the right size to hold the string

    strcpy (dic[i], buf); // copy the data to this new storage
}
Alexander Gelbukh
  • 2,104
  • 17
  • 29
0

The key thing to understand for both of your examples is that a char * value stores the address of a byte in memory. By convention, C strings are represented as a pointer to the first byte of the string, with a null byte marking the end. When you assigned constant strings into your array, the compiler allocated the necessary memory and placed the pointers into your array, but when you are not using constants it is your responsibility to allocate the buffer to store the string, and then store that pointer in the array yourself.

In your second example you have allocated storage for several pointers to char, but you have not made those pointers refer to valid buffers, so accessing them with either return garbage or crash the program. There are (at least) two ways to address this: either allocate a fixed-size buffer on the stack and store your data there, or dynamically allocate memory from the heap using malloc.

The former has the advantage of handling the deallocation of the buffers automatically, but requires you to decide at compile time how much memory to allocate for each string:

char* dic[tam];
char buf[tam * 32]; // allocate 32 bytes per element.
for (int i = 0; i < tam; i++) {
    // Make the pointers in ``dic`` refer to 32-byte offsets into the buffer.
    dic[tam] = &(buf[tam * 32]);
}

You can also allocate dynamically using malloc. You could actually allocate one big tam * 32 buffer this way too, but for the sake of example here's how to allocate a separate buffer for each element:

char* dic[tam];
for (int i = 0; i < tam; i++) {
    // Allocate 32 bytes per element.
    // (This value can be decided at runtime, if you want.)
    dic[tam] = malloc(32);
}

But since this uses malloc you need to be sure to clean up this memory before you return to avoid a memory leak. e.g. at the end of your routine:

for (int i = 0; i < tam; i++) {
    // de-allocate the buffer we allocated earlier
    free(dic[tam]);
}

(This method of calling malloc multiple times in a loop may also cause memory fragmentation if you do it a lot, but that's an advanced topic not worth worrying about for a small program.)

Martin Atkins
  • 62,420
  • 8
  • 120
  • 138
  • That answers the first half of the question… – icktoofay Jul 27 '14 at 00:50
  • I know, I got it. I read it in another question but I wondering why I can't allocate the array in memory. If I store it like dic[0] my program crashes. – c_str Jul 27 '14 at 00:54
  • I see that the question is now only the first part that I answered originally. If the other part has been split into a second question I'd appreciate a link to it so I can move the second part of my answer over there. – Martin Atkins Jul 27 '14 at 01:07
  • I never asked for the sizeof. I just mentioned "I don't know why". But never asked. You are supposed to be engineer. You have to learn FULL and SPECIFIC any question! From all the aprox. 10 persons who commented and answered got it all wrong. Just BLUE ans Alexander learned to read. I had to edit my question because someone else edited asking for sizeof when my main question wasn't even that. Never asked for sizeof. I asked for STORING an array. That's even my title. – c_str Jul 27 '14 at 01:14
  • Very well. I removed the first part of my answer so that it now answers the new form of the question that doesn't discuss the ``sizeof`` issue. (Though the bug still exists in the example in your question.) – Martin Atkins Jul 27 '14 at 01:20