Разница между char [] [] и char **, почему put (strings [0]) не может печатать (strings определяется как char ** strings) - PullRequest
0 голосов
/ 16 февраля 2019

Как я могу напечатать массив строк, вызвав такую ​​функцию:

void function(char**string);    //sample1
void function(char string[][LEN2], int size);    //sample2
void function(char (*string)[LEN2], int size);    //sample3

Я думаю, что 2 и 3 - это правильно;

Правильный формат этой проблемы не важен.

Я хочу знать, как компьютер понимает sample1 (особенно в памяти), а не просто записывать правильный ответ.

Спасибо. (Мое первое использование может быть немного нелепым.)

использовать визуальную студию 2017 года, закрыть безопасную проверку.работает на ПК.

#include<stdio.h>
#define LEN1 10
#define LEN2 100
void item1(char**string);
void print_initial_string(char**string);

int main(void)
{
    char string[LEN1][LEN2] = {"a", "ab", "abc", "abcd", "abcde",
            "c", "cd", "cde", "cdgh", "seids"};
    item1(string);
}

/*implements of functions*/
void item1(char**string)
{
    print_initial_string(string);
}
void print_initial_string(char**string)
{
    char (*c)[LEN2] = string[0];
    for (int i = 0; i < LEN1; i++)
        puts(c);     /*-- stopped at here --*/
}

Я думаю, что он напечатает строку, но это не удалось.

И вернет код -1073741819

Ответы [ 2 ]

0 голосов
/ 18 февраля 2019

Это программа, которую я написал, чтобы понять проблему, и ответ в комментарии.

#include<stdio.h>
#define LEN1 10
#define LEN2 100
int main(void)
{
    //first method to define a string array(using array)
    char string0[LEN1][LEN2] = {"a", "ab", "abc", "abcd", "abcde",
                           "c", "cd", "cde", "cdgh", "seids"};
    //char(*c0)[LEN2] = string0;    //right
    char ** c1 = string0;    //wrong!

    //second method to define a string array(using pointer)
    char *string1[LEN1] = { "a", "ab", "abc", "abcd", "abcde",
                        "c", "cd", "cde", "cdgh", "seids" };
    char **c3 = string1;

    //for using array:
    printf("string0 = %p\n", string0);
    printf("string0 + 1 = %p\n", string0 + 1);
    printf("sizeof(string0) = %u\n", sizeof(string0));    //1000
    printf("string0[0] = %p\n", string0[0]);
    printf("string0[0] + 1 = %p\n", string0[0] + 1);
    printf("sizeof(string0[0]) = %u\n", sizeof(string0[0]));    //100

    printf("\n");
    printf("c1 = %p\n", c1);
    printf("sizeof(c1[0]) = %d\n", sizeof(c1[0]));
    printf("c1[0] = %p\n", c1[0]);    //suppose c1[0] is a pointer
    //61
    printf("'a' = %x\n", 'a');    //some thing has been clear
    //61
    /*
    my thinking:
        In c program, the value of a pointer just indecate which memory cell it 
    refers. And what program looks a pointer like may be embodied in the value of
    "sizeof" operator. For example:
        sizeof(string0) = 1000, so string0 is a whole reference of the array.
        sizeof(string0[0]) = 100, so string0[0] is a row in that array.
        If add one to string0, we find it is bigger 100 than old one.
        If add one to string0[0], we find it is bigger 1 than old one.
        Though both of string0 and string0[0] has the same content.

        So, it is not important that string0's and string0[0]'s same content.
        But what will hapen when string0 + 1 and string0[0] + 1.
        pointer + integer = value(pointer) + sizeof(pointer)*integer;
        value(a):the content of a;

        c1's content is same as string0, program regard c1[0] as a pointer.
    But c1[0]'s value is character 'a'. So, the program failed.
    */
    return 0;
}
0 голосов
/ 16 февраля 2019

Если я компилирую, делая gcc -pedantic -Wextra ar.c, я получаю много сообщений, указывающих на проблемы:

pi@raspberrypi:~/Downloads $ gcc -pedantic -Wextra ar.c
ar.c: In function ‘main’:
ar.c:11:11: warning: passing argument 1 of ‘item1’ from incompatible pointer type [-Wincompatible-pointer-types]
     item1(string);
           ^~~~~~
ar.c:4:6: note: expected ‘char **’ but argument is of type ‘char (*)[100]’
 void item1(char**string);
      ^~~~~
ar.c: In function ‘print_initial_string’:
ar.c:21:23: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
     char (*c)[LEN2] = string[0];
                       ^~~~~~
ar.c:23:14: warning: passing argument 1 of ‘puts’ from incompatible pointer type [-Wincompatible-pointer-types]
         puts(c);     /*-- stopped at here --*/
              ^
In file included from ar.c:1:0:
/usr/include/stdio.h:697:12: note: expected ‘const char *’ but argument is of type ‘char (*)[100]’
 extern int puts (const char *__s);
            ^~~~

char**string - это массив char*, это означает, что каждая запись в string - это char* (так что указатель), это не то, что символьная строка [LEN1] [LEN2] , потому что она не содержит указателей

Так что void item1(char (*string)[LEN2]) и void print_initial_string(char (*string)[LEN2])

char (*c)[LEN2] = string[0]; тоже не в порядке, c - это char *, но вы говорите, что это указатель на char[LEN2] Вы хотите char (*c)[LEN2] = &string[0]; или просто char (*c)[LEN2] = string;.В этом случае puts(c) должно быть puts(c[i]);, потому что c не строка, а указатель на

Наконец:

#include<stdio.h>

#define LEN1 10
#define LEN2 100

void item1(char (*string)[LEN2]);
void print_initial_string(char (*string)[LEN2]);

int main(void)
{
    char string[LEN1][LEN2] = {"a", "ab", "abc", "abcd", "abcde",
                               "c", "cd", "cde", "cdgh", "seids"};
    item1(string);
}

/*implements of functions*/
void item1(char (*string)[LEN2])
{
    print_initial_string(string);
}
void print_initial_string(char (*string)[LEN2])
{
  char (*c)[LEN2] = string;

  for (int i = 0; i < LEN1; i++)
    puts(c[i]);
}

Компиляция и выполнение:

pi@raspberrypi:~/Downloads $ gcc -g -pedantic -Wextra ar.c
pi@raspberrypi:~/Downloads $ ./a.out
a
ab
abc
abcd
abcde
c
cd
cde
cdgh
seids

Выполнение под valgrind :

pi@raspberrypi:~/Downloads $ valgrind ./a.out
==11987== Memcheck, a memory error detector
==11987== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==11987== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==11987== Command: ./a.out
==11987== 
a
ab
abc
abcd
abcde
c
cd
cde
cdgh
seids
==11987== 
==11987== HEAP SUMMARY:
==11987==     in use at exit: 0 bytes in 0 blocks
==11987==   total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==11987== 
==11987== All heap blocks were freed -- no leaks are possible
==11987== 
==11987== For counts of detected and suppressed errors, rerun with: -v
==11987== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)

Пример, где char** является правильным:

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

#define LEN 10

void pr(const char ** a, int sz)
{
  for (int i = 0; i != sz; ++i)
    puts(a[i]);
}

int main()
{
  const char *a[LEN] = { "a", "ab", "abc", "abcd", "abcde",
                         "c", "cd", "cde", "cdgh", "seids"};

  pr(a, LEN);
}

Я использую const , потому что литеральные строки являются постоянными

Компиляция и выполнение:

pi@raspberrypi:/tmp $ gcc -pedantic -Wall aa.c
pi@raspberrypi:/tmp $ ./a.out
a
ab
abc
abcd
abcde
c
cd
cde
cdgh
seids
...