当我的输入大小足够大时,分段错误萌芽,在项目中使用可变长度数组.我想删除它们,如何让GCC显示它找到的可变长度数组的每个声明?
我已经尝试过使用-Wstack-usage=1000和过滤消息warning: stack usage might be unbounded,但这给了我功能,而不是声明.有没有更好的办法?
本以为C不会再给我带来惊喜了,但这却让我大吃一惊。
const int NUM_FOO = 5;
....
int foo[NUM_FOO];
==>error C2057: expected constant expression
Run Code Online (Sandbox Code Playgroud)
我的 C++ 经验让我在内部#define尽可能地反对。所以这真是一个惊喜。VS2019,使用/TC编译。我认为 C99 无论如何都允许可变大小的数组。
任何人都可以解释为什么会发生拒绝,因为编译器在编译时肯定知道数组的大小?
C99不是允许可变大小数组吗?
我在函数中声明了许多指向可变长度数组(VLA)的指针来动态分配二维数组;例如,
int M, N; // have some value
double (*arr1)[N] = calloc(M, sizeof(double [N]));
double (*arr2)[N] = calloc(M, sizeof(double [N]));
double (*arr3)[N] = calloc(M, sizeof(double [N]));
... // so many declarations
Run Code Online (Sandbox Code Playgroud)
因为函数变得很长,所以我尝试将其分成几个函数,每个函数都需要所有指针作为参数。我没有在函数中传递许多东西(这对性能不利),而是声明了一个全局包含所有指针的结构,以减少参数数量:
struct ptrpack {
int M, N;
double (*arr1)[N];
double (*arr2)[N];
...
};
// then each function just takes a single struct rather than many pointers
void foo(struct ptrpack p) {
...
}
Run Code Online (Sandbox Code Playgroud)
但是,struct 中不允许存在指向 VLA 的指针。如果结构定义位于函数中,则 GCC 扩展允许这样做,但在我的例子中,定义位于全局范围内。
这个问题的最佳解决方案是什么?我强烈喜欢使用指向 VLA 的指针,而不是普通的指针。
typedef VLA 是否需要计算大小表达式?
int f(void);
int main(void)
{
typedef int (T) [ f() ]; // is f required to be evaluated ?
T x;
return sizeof x;
}
Run Code Online (Sandbox Code Playgroud)
指向 VLA 的typedef指针是否需要计算大小表达式?
int f(void);
int main(void)
{
typedef int (*T) [ f() ]; // is f required to be evaluated ?
T x;
return sizeof x;
}
Run Code Online (Sandbox Code Playgroud)
UPD。在 isvisible 的定义中f,那么对它的调用可能会被优化掉:
int f(void)
{
return 4;
}
int main(void)
{
typedef int (*T) [ f() ];
return sizeof(T); …Run Code Online (Sandbox Code Playgroud) 我正在动态计算数组的大小.就像是:
void foo(size_t limit)
{
char buffer[limit * 14 + 1];
}
Run Code Online (Sandbox Code Playgroud)
但只是GCC编译器说:
error: ISO C90 forbids variable length array ‘buffer’
Run Code Online (Sandbox Code Playgroud)
搜索SO我发现这个答案:
C99§6.7.5.2:
如果size是一个不是整数常量表达式的表达式......每次计算它时,它的值应大于零.
所以,我做了大小限制类型变量的重新声明:
void foo(const size_t limit)
Run Code Online (Sandbox Code Playgroud)
但它继续给我警告.这是GCC的错误吗?
C有一个很酷的功能叫做可变长度数组.它在C90及更高版本中可用,它允许延迟阵列的大小直到运行时.参见GCC的手册6.19可变长度阵列.
我在C++工作.在std=c++11,由于使用了allocaCygwin ,我正在捕获编译失败.如果可能,我想切换到可变长度数组.我也想尝试避免std::vector,std::array因为我想要远离内存管理器.我相信每一点点都有帮助,所以我很乐意抓住这些机会(有些人认为是窥视孔).
我可以在C++ 03和C++ 11中使用可变长度数组吗?
我已经在ISO C99委员会草案中看到,结构可能有一个不完整的数组,其末端具有未指定的大小,称为Flexible Array Member.
另一方面,C99还具有可变长度数组,它允许在编译时声明大小不恒定的数组.
我认为FAM是一种特殊的VLA,但我看到有两个SO用户声称不是.此外,阅读维基百科部分sizeof,它表示这sizeof两者的行为不同.
为什么它们都存在而不只是一个?(他们的用例太不一样了吗?)
此外,哪些其他相关行为对于每个行为都不同?
根据另一个帖子中某人的评论:
VLA引入了比它们解决的问题更多的问题,因为您永远不知道声明是否会因为x对于堆栈来说太大而崩溃.
这段代码会溢出,因为sizeof(a)堆栈太长了:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int n = 100000000;
int a[4][n];
printf("%zu\n", sizeof(a));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是这个不能因为sizeof(a)8(我的计算机中指针的大小):
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int n = 100000000;
int (*a)[n];
printf("%zu\n", sizeof(a));
a = malloc(sizeof(*a) * 4);
free(a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我的假设是否正确?
我们可以根据对象确定是否使用VLA是危险的(可能会溢出)sizeof吗?
以下是一个MergeSort实现。我的问题是,编译器抱怨std::begin无法将其应用于可变大小的数组 temp以进一步使用std:copy。
我正在使用C ++ 17和gcc 8.3。
template<typename Container, typename Iterator>
void Search::MergeSort(Container &array, Iterator begin, Iterator end)
{
auto const len = end - begin;
if (len > 1)
{
auto mid = begin + len / 2;
MergeSort(array, begin, mid);
MergeSort(array, mid, end);
typename Container::value_type temp[len];
int p = 0;
for (auto i = begin, j = mid; i < mid; ++i)
{
auto curr = *i; …Run Code Online (Sandbox Code Playgroud) 如果C语言中的数组大小固定,那么此代码如何正常工作?这段代码有效,但是我的老师说我做错了。
int main()
{
int n,element,i;
printf("Enter the size of Array : ");
scanf("%d",&n);
int a[n];
for(i=0;i<n;i++){
printf("Enter %d no element : ",i+1);
scanf("%d",&a[i]);
}
printf("Enter the new element to be inserted at the End: ");
scanf("%d",&element);
n=n+1;
a[n-1]=element;
for(i=0;i<n;i++){
printf("%d\t",a[i]);
}
}
Run Code Online (Sandbox Code Playgroud)