如何通过调用如下函数来打印字符串数组:
void function(char**string); //sample1
void function(char string[][LEN2], int size); //sample2
void function(char (*string)[LEN2], int size); //sample3
我认为2和3是正确的;
此问题的正确格式并不重要。
我想知道,计算机如何理解sample1(尤其是在内存中)而不仅仅是记录正确的答案。
谢谢。(我第一次使用,可能有点荒谬。)
使用Visual Studio 2017,关闭安全检查。在PC上运行。
#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
答案 0 :(得分:1)
如果我编译时进行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*
(所以是指针),这不是 char string [LEN1] [LEN2] 是因为其中不包含指针
所以void item1(char (*string)[LEN2])
和void print_initial_string(char (*string)[LEN2])
char (*c)[LEN2] = string[0];
也不行, c 是 char * ,但是您说它是指向char[LEN2]
的指针,您想{ {1}}或仅char (*c)[LEN2] = &string[0];
。在这种情况下,char (*c)[LEN2] = string;
必须为puts(c)
,因为 c 不是字符串,而是指向
最后:
puts(c[i]);
编译和执行:
#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]);
}
在 valgrind 下执行:
pi@raspberrypi:~/Downloads $ gcc -g -pedantic -Wextra ar.c
pi@raspberrypi:~/Downloads $ ./a.out
a
ab
abc
abcd
abcde
c
cd
cde
cdgh
seids
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**
我使用 const 因为文字字符串是const
编译和执行:
#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);
}
答案 1 :(得分:0)
这是我编写的用于了解问题的程序,答案在注释中。
#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;
}