在C中存储char *数组

时间:2014-07-27 00:41:55

标签: c arrays sizeof

我正在尝试创建和存储char*数组。

所以,首先我尝试了这个:

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]);
}

它适用于此OUTPUT:

  

您好   喵喵   Miau miau = 3

如果我尝试:

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");
}

显示不可读的内容,例如&#34; 0xassdfsdf&#34;

我该怎样做才能将它存储在内存中?

3 个答案:

答案 0 :(得分:2)

一个问题是

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

应该是

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

因为数组包含指向存储的指针,而不是存储本身,你应该传递给scanf的是这个指针。实际上,char*只是一个4字节的指针。数组char* dic[tam]包含一些这样的指针,因此dic[0]是指向char的4字节指针,&dic[0]是此指针的地址。

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

只是覆盖此指针并在其后破坏内存。

另一个问题是你没有初始化数组,所以它没有指向任何存储。

char* dic[tam];

此处数组包含指向内存中随机位置的指针。

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

很可能这完全失败了。因此,在printf中,您可以打印指向内存中随机位置的指针。

(坏)解决方案是:

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]
}

或(略好)

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
}

答案 1 :(得分:2)

#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;
}

答案 2 :(得分:0)

对于这两个示例,要理解的关键是char *值将字节的地址存储在内存中。按照惯例,C字符串表示为指向字符串第一个字节的指针,其中空字节标记结尾。当您将常量字符串分配到数组中时,编译器会分配必要的内存并将指针放入您的数组中,但是当您不使用常量时,您有责任分配缓冲区来存储字符串,然后将该指针存储在排队自己。

在你的第二个例子中,你已经为char的几个指针分配了存储空间,但你没有让那些指针引用有效的缓冲区,所以使用return garbage或者程序崩溃来访问它们。有(至少)两种方法来解决这个问题:要么在堆栈上分配固定大小的缓冲区并在那里存储数据,要么使用malloc从堆中动态分配内存。

前者具有自动处理缓冲区释放的优点,但需要您在编译时决定为每个字符串分配多少内存:

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]);
}

您还可以使用malloc动态分配。你实际上也可以用这种方式分配一个大的tam * 32缓冲区,但为了举例说明,如何为每个元素分配一个单独的缓冲区:

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);
}

但由于这使用malloc,因此您需要确保在返回之前清理此内存以避免内存泄漏。例如在你的日常工作结束时:

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

(这种在循环中多次调用malloc的方法如果你做了很多事,也可能导致内存碎片化,但这是一个不值得为小程序担心的高级主题。)< / p>