不,等等,忍受我...
VLA一直是GCC扩展,但它们被C99采用:
[C99: 6.7.5.2/4]:如果大小不存在,则数组类型是不完整类型.如果大小是*而不是表达式,则数组类型是未指定大小的可变长度数组类型,只能在具有函数原型范围的声明中使用; 尽管如此,这些数组仍然是完整类型.如果size是一个整型常量表达式,并且元素类型具有已知的常量大小, 则数组类型不是可变长度数组类型; 否则,数组类型是可变长度数组类型.
C99也称为ISO/IEC 9899:1999.
现在:
[C++11: 1.1/2]:C++是基于ISO/IEC 9899:1999(以下称为C标准)中规定的C编程语言的通用编程语言.除了C提供的功能之外,C++还提供其他数据类型,类,模板,异常,命名空间,运算符重载,函数名称重载,引用,免费存储管理操作符和其他库设施.
那么C++ 11也不应该有VLA吗?
我知道restrictC中的限定符指定两个指针指向的内存区域不应重叠。据我了解,Linux(不是 SUS)原型看起来memcpy像 -
void* memcpy(void *restrict dest, const void *restrict src, size_t count);
Run Code Online (Sandbox Code Playgroud)
然而,当我查看man7.org/memcpy时,声明似乎是 -
void *memcpy(void dest[restrict .n], const void src[restrict .n], size_t n);
Run Code Online (Sandbox Code Playgroud)
我的问题是 -
.前面的是什么n意思?我熟悉可变长度数组声明。变量的 for是否.出现在数组指定之后?这是标准的一部分吗?有两种方法可以为数组分配内存,其大小在开始时是未知的.最常见的方式是使用malloc这样的
int * array;
... // when we know the size
array = malloc(size*sizeof(int));
Run Code Online (Sandbox Code Playgroud)
但是在我们知道尺寸后,在C99中定义数组也是有效的.
... // when we know the size
int array[size];
Run Code Online (Sandbox Code Playgroud)
他们完全一样吗?
如何在MS Visual C++中启用使用C99中定义的VLA或可变长度数组,或者根本不可能使用?
是的我知道C++标准是基于C89的,并且VGA在C89标准中不可用,因此在C++中不可用,但MSVC++也应该是C编译器,可以使用/ TC编译器参数(Compile as C Code (/TC)).但这样做似乎并没有启用VLA,并且在构建为C++(Compile as C++ Code (/TP))时编译过程失败并出现相同的错误.也许MSVC++ C编译器只符合C89或者我缺少一些东西(一些特殊的构造或pragma/define)?
代码示例:
#include <stdlib.h>
int main(int argc, char **argv)
{
char pc[argc+5];
/* do something useful with pc */
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
编译错误:
错误C2057:预期的常量表达式
错误C2466:无法分配常量大小为0的数组
错误C2133:'pc':未知大小
使用VLA(可变长度数组)有一些奇怪的代码,它被gcc 4.6视为有效C(C99,C11):
$ cat a.c
int main(int argc,char**argv)
{
struct args_t{
int a;
int params[argc]; // << Wat?
// VLA in the middle of some struct, between other fields
int b;
} args;
args.b=0;
for(args.a=0;args.a<argc;args.a++)
{
args.params[args.a]=argv[0][0];
args.b++;
}
return args.b;
}
Run Code Online (Sandbox Code Playgroud)
此代码编译时没有警告:
$ gcc-4.6 -Wall -std=c99 a.c && echo $?
0
$ ./a.out ; echo $?
1
$ ./a.out 2; echo $?
2
$ ./a.out 2 3; echo $?
3
Run Code Online (Sandbox Code Playgroud)
同样的-std=c1x:
$ gcc-4.6 -Wall -std=c1x a.c && …Run Code Online (Sandbox Code Playgroud) 我一直想知道如何逃脱这个:
int main(int argc, char **argv) {
printf("%p %s %d\n", &argv[1], argv[1], strlen(argv[1]));
char copy[strlen(argv[1]) + 1];
strcpy(copy, argv[1]);
printf("%p %s %d\n", ©, copy, strlen(copy));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
copy无论如何,char数组都被分配,程序运行正常,打印出原始数据和副本.而Valgrind并没有抱怨什么.
我认为没有malloc的C语言中不可能使用动态数组.我错了吗?
我知道sizeof永远不会评估它的操作数,除非在所述操作数是VLA的特定情况下.或者,我以为我知道.
void g(int n) {
printf("g(%d)\n", n);
}
int main(void) {
int i = 12;
char arr[i]; // VLA
(void)sizeof *(g(1), &arr); // Prints "g(1)"
(void)sizeof (g(2), arr); // Prints nothing
return 0;
}
Run Code Online (Sandbox Code Playgroud)
到底是怎么回事?
以防万一,这是在Coliru上用GCC 5.1编译的.
我正在声明一个二维数组:
char arr[10][10];
arr[0][0] = 'X';
Run Code Online (Sandbox Code Playgroud)
现在我在调试器中打印;
(lldb) po arr[0][0]
'X'
Run Code Online (Sandbox Code Playgroud)
真棒!没问题.
现在我正在声明一个二维数组:
int col = 10;
int row = 10;
char arr[row][col];
arr[0][0] = 'X';
Run Code Online (Sandbox Code Playgroud)
现在我在调试器中打印;
(lldb) po arr[0][0]
error: subscript of pointer to incomplete type 'char []'
error: 1 errors parsing expression
Run Code Online (Sandbox Code Playgroud)
为什么??
在初始化可变长度数组编译器时会给出错误消息:
[Error] variable-sized object may not be initialized
Run Code Online (Sandbox Code Playgroud)
代码段:
int n;
printf("Enter size of magic square: ");
scanf("%d",&n);
int board[n][n] = {0};
Run Code Online (Sandbox Code Playgroud)
如何初始化可变长度数组?为什么所有元素都没有0按照以下方式初始化;
int board[n][n];
board[n][n] = {0};
Run Code Online (Sandbox Code Playgroud)
?
这个答案的评论部分中的一个论点促使我提出这个问题.
在以下代码中,bar指向可变长度数组,因此sizeof在运行时而不是编译时确定.
int foo = 100;
double (*bar)[foo];
Run Code Online (Sandbox Code Playgroud)
该论点是关于sizeof当操作数是可变长度数组时是否使用计算其操作数,在未初始化sizeof(*bar)时产生未定义的行为bar.
是否使用未定义的行为,sizeof(*bar)因为我正在取消引用未初始化的指针?sizeof当类型是可变长度数组时,是实际评估的操作数,还是仅确定其类型(sizeof通常如何工作)?
编辑:每个人似乎都引用了C11选秀中的这段话.有谁知道这是否是官方标准中的措辞?