可以将临时指针数组传递给 C 中的函数吗?
Can a temporary array of pointer be passed to a function in C?
在下面的代码中,我想用一个临时指针数组调用函数 f()
或 f2()
,如第 33 和 39 行 ...
#include <stdio.h>
void f( const char** const p, size_t num )
{
size_t i;
for ( i = 0; i < num; ++i )
{
printf( "%s\n", p[ i ] );
}
}
void f2( const char* const p[2] )
{
size_t i;
for ( i = 0; i < 2; ++i )
{
printf( "%s\n", p[ i ] );
}
}
void withPtrArray()
{
const char* tmp[] = { "hello", "world" };
const char** p;
// This compiles/runs fine:
f( tmp, sizeof tmp / sizeof( const char* ) );
// This also compiles/runs fine:
f( ( p = tmp ), 2 );
// This does not compile - I'm not clear why.
f( ( { "hello", "world" } ), 2 );
// My last hope: I thought a function that explicitly took a pointer array:
// This works...
f2( tmp );
// ...but this does not:
f2( { "hello", "world" } );
}
void g( const char* const p )
{
printf( "%s\n", p );
}
// Analog to f2()
void g2( const char p[12] )
{
printf( "%s\n", p );
}
// These analogs with an array of chars work fine.
void withPtr()
{
const char tmp[] = "hello world";
const char* p = tmp;
g( tmp );
g( ( p = tmp ) );
g( ( "hello world" ) );
g2( tmp );
g2( "hello world" );
}
int main( int argc, char* argv[] )
{
withPtrArray();
withPtr();
return 0;
}
...但是这些行编译失败...
prog.c: In function ‘withPtrArray’:
prog.c:33:17: warning: left-hand operand of comma expression has no effect [-Wunused-value]
f( ( { "hello", "world" } ), 2 );
^
prog.c:33:27: error: expected ‘;’ before ‘}’ token
f( ( { "hello", "world" } ), 2 );
^
prog.c:33:6: warning: passing argument 1 of ‘f’ from incompatible pointer type [-Wincompatible-pointer-types]
f( ( { "hello", "world" } ), 2 );
^
prog.c:3:6: note: expected ‘const char ** const’ but argument is of type ‘char *’
void f( const char** const p, size_t num )
^
prog.c:39:7: error: expected expression before ‘{’ token
f2( { "hello", "world" } );
^
我从 C 迁移到 C++ 已经有几年了,但我不认为这是 C 和 C++ 语法差异的问题。
是否有允许将临时指针数组传递给函数的 C 语法?
f( ( { "hello", "world" } ), 2 )
的问题在于:函数的参数必须是表达式。但是,其他表达式的花括号列表本身并不是表达式。
也许您错误地将 { "hello", "world" }
视为可能具有类型 "array of 2 char arrays" 的表达式。但事实并非如此。您可能已经注意到 { "hello" };
也不是有效代码:每个表达式都可以通过在其后加上 ;
变成一个语句,因此 {"hello"}
不能是一个表达式。
以下代码也不起作用:
char *c[2];
c = { "hello", "world" };
甚至:
int y;
y = { 5 };
在这两种情况下,赋值运算符后面都必须跟一个表达式;但是没有表达式的语法由大括号内的内容组成。
大括号列表只能作为声明 的初始值设定项出现,或出现在复合文字中。大括号表示存在初始值设定项列表。
声明的结构是类型名和声明符,后跟 =
符号(这不是赋值运算符,因为这不是表达式),然后是初始化程序。初始化器可以是表达式,也可以是初始化器的花括号列表。这样声明的意思是,每个初始化器都被视为声明中声明的对象之一的初始值。
在您的代码中,您可以使用复合文字:
f( (const char *[2]){ "hello", "world" }, 2 );
复合文字的剖析是,它是为该类型的对象提供带有初始值设定项的类型名称的语法;它不是应用于某种表达式的转换运算符。
在下面的代码中,我想用一个临时指针数组调用函数 f()
或 f2()
,如第 33 和 39 行 ...
#include <stdio.h>
void f( const char** const p, size_t num )
{
size_t i;
for ( i = 0; i < num; ++i )
{
printf( "%s\n", p[ i ] );
}
}
void f2( const char* const p[2] )
{
size_t i;
for ( i = 0; i < 2; ++i )
{
printf( "%s\n", p[ i ] );
}
}
void withPtrArray()
{
const char* tmp[] = { "hello", "world" };
const char** p;
// This compiles/runs fine:
f( tmp, sizeof tmp / sizeof( const char* ) );
// This also compiles/runs fine:
f( ( p = tmp ), 2 );
// This does not compile - I'm not clear why.
f( ( { "hello", "world" } ), 2 );
// My last hope: I thought a function that explicitly took a pointer array:
// This works...
f2( tmp );
// ...but this does not:
f2( { "hello", "world" } );
}
void g( const char* const p )
{
printf( "%s\n", p );
}
// Analog to f2()
void g2( const char p[12] )
{
printf( "%s\n", p );
}
// These analogs with an array of chars work fine.
void withPtr()
{
const char tmp[] = "hello world";
const char* p = tmp;
g( tmp );
g( ( p = tmp ) );
g( ( "hello world" ) );
g2( tmp );
g2( "hello world" );
}
int main( int argc, char* argv[] )
{
withPtrArray();
withPtr();
return 0;
}
...但是这些行编译失败...
prog.c: In function ‘withPtrArray’:
prog.c:33:17: warning: left-hand operand of comma expression has no effect [-Wunused-value]
f( ( { "hello", "world" } ), 2 );
^
prog.c:33:27: error: expected ‘;’ before ‘}’ token
f( ( { "hello", "world" } ), 2 );
^
prog.c:33:6: warning: passing argument 1 of ‘f’ from incompatible pointer type [-Wincompatible-pointer-types]
f( ( { "hello", "world" } ), 2 );
^
prog.c:3:6: note: expected ‘const char ** const’ but argument is of type ‘char *’
void f( const char** const p, size_t num )
^
prog.c:39:7: error: expected expression before ‘{’ token
f2( { "hello", "world" } );
^
我从 C 迁移到 C++ 已经有几年了,但我不认为这是 C 和 C++ 语法差异的问题。
是否有允许将临时指针数组传递给函数的 C 语法?
f( ( { "hello", "world" } ), 2 )
的问题在于:函数的参数必须是表达式。但是,其他表达式的花括号列表本身并不是表达式。
也许您错误地将 { "hello", "world" }
视为可能具有类型 "array of 2 char arrays" 的表达式。但事实并非如此。您可能已经注意到 { "hello" };
也不是有效代码:每个表达式都可以通过在其后加上 ;
变成一个语句,因此 {"hello"}
不能是一个表达式。
以下代码也不起作用:
char *c[2];
c = { "hello", "world" };
甚至:
int y;
y = { 5 };
在这两种情况下,赋值运算符后面都必须跟一个表达式;但是没有表达式的语法由大括号内的内容组成。
大括号列表只能作为声明 的初始值设定项出现,或出现在复合文字中。大括号表示存在初始值设定项列表。
声明的结构是类型名和声明符,后跟 =
符号(这不是赋值运算符,因为这不是表达式),然后是初始化程序。初始化器可以是表达式,也可以是初始化器的花括号列表。这样声明的意思是,每个初始化器都被视为声明中声明的对象之一的初始值。
在您的代码中,您可以使用复合文字:
f( (const char *[2]){ "hello", "world" }, 2 );
复合文字的剖析是,它是为该类型的对象提供带有初始值设定项的类型名称的语法;它不是应用于某种表达式的转换运算符。