相关疑难解决方法(0)

为什么变长数组不是C++标准的一部分?

在过去的几年里,我并没有非常使用过C语言.当我今天读到这个问题时,我遇到了一些我不熟悉的C语法.

显然在C99中,以下语法有效:

void foo(int n) {
    int values[n]; //Declare a variable length array
}
Run Code Online (Sandbox Code Playgroud)

这似乎是一个非常有用的功能.有没有关于将它添加到C++标准的讨论,如果是这样,为什么它被省略?

一些潜在的原因:

  • 毛茸茸的编译器供应商实现
  • 与标准的其他部分不兼容
  • 可以使用其他C++构造模拟功能

C++标准规定数组大小必须是常量表达式(8.3.4.1).

是的,当然我意识到在玩具示例中可以使用std::vector<int> values(m);,但这会从堆中分配内存而不是堆栈.如果我想要一个多维数组,如:

void foo(int x, int y, int z) {
    int values[x][y][z]; // Declare a variable length array
}
Run Code Online (Sandbox Code Playgroud)

vector版本变得很笨拙:

void foo(int x, int y, int z) {
    vector< vector< vector<int> > > values( /* Really painful expression here. */);
}
Run Code Online (Sandbox Code Playgroud)

切片,行和列也可能遍布整个内存.

看一下comp.std.c++这个问题的讨论很明显,这个问题在争论的两个方面都有一些非常重要的名字引起争议.毫无疑问,a std::vector总是更好的解决方案.

c++ arrays standards variable-length variable-length-array

311
推荐指数
7
解决办法
14万
查看次数

使用可变长度数组有任何开销吗?

使用可变长度数组有一些开销吗?可以在运行时通过命令行参数传递数组的大小吗?与自动和动态分配数组相比,为什么会引入它?

c arrays variable-length-array

46
推荐指数
2
解决办法
2万
查看次数

语句goto不能跨变量定义?

假设这些代码编译成g++:

#include <stdlib.h>

int main() {
    int a =0;

    goto exit;

    int *b = NULL;

exit:
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

g++ 会抛出错误:

goto_test.c:10:1: error: jump to label ‘exit’ [-fpermissive]
goto_test.c:6:10: error:   from here [-fpermissive]
goto_test.c:8:10: error:   crosses initialization of ‘int* b’
Run Code Online (Sandbox Code Playgroud)

似乎goto无法跨越指针定义,但gcc编译好,没有任何抱怨.

修复错误之后,我们必须在任何goto语句之前声明所有指针,也就是说你必须声明这些指针,即使你现在不需要它们(并且违反了一些原则).

什么原因设计考虑g++禁止有用的尾部goto声明?


更新:

goto可以交叉变量(任何类型的变量,不限于指针)声明,但除了那些获得初始化值.如果我们删除NULL上面的任务,g++请立即保持沉默.因此,如果要声明goto-cross-area 之间的变量,请不要初始化它们(并且仍然违反某些原则).

goto g++

23
推荐指数
2
解决办法
2万
查看次数

C99型VLA有哪些技术缺点?

我从许多人那里听说,在C99中引入的可变长度阵列非常糟糕.IRC的一些人在一分钟之前说过"我不认为C++会得到VLA,而strousoup对他们做了一些非常负面的评论".

这些人讨厌VLA的原因是什么?

c c++ c99 variable-length-array c++11

11
推荐指数
3
解决办法
1457
查看次数

alloca完全可以替换吗?

我已经阅读了很多alloca过时的地方,不应该使用,而应该使用可变长度数组.

我的问题是:alloca可变长度数组是否完全可以替换?

在我的特定实例中,我有一些看起来像这样的东西:

typedef struct { 
  int *value; 
  size_t size; 
  } some_type;

void SomeExternalFunction(some_type);

...

void foo(){
  //What I thought to do
  some_type bar;
  bar.value=alloca(sizeof(int)*10);
  SomeExternalFunction(bar);

  //what should be done without alloca
  some_type fizz;
  int tmp[10];
  fizz.value=tmp;
  SoemExternalFunction(fizz);
}
Run Code Online (Sandbox Code Playgroud)

我错过了什么或者这是对alloca的实际使用吗?另外假设这个例子由于某种原因我想要在堆栈上分配值

c arrays alloca

8
推荐指数
1
解决办法
2230
查看次数

struct 和 struct 成员的数组元素

我想问一下 C 中的 struct 声明。例如,

struct Person
{
    char name[50];
    int citNo;
    float salary;
} prsn[20];
Run Code Online (Sandbox Code Playgroud)

有什么作用[20]?这是什么意思?是将名称限制为 20(从 50)还是将prsnfrom限制prsn[1]prsn[20]

如果我写这样的代码:

struct Person
{
    char name[50];
    int citNo;
    float salary;
};
struct Person prsn[20];
Run Code Online (Sandbox Code Playgroud)

它做同样的事情吗?

c struct

8
推荐指数
2
解决办法
564
查看次数

是否需要从堆栈中分配C可变长度数组?

从我们的嵌入式系统代码中删除对malloc和calloc的所有调用后,我惊讶地发现malloc仍然被链接.调用图指向一个没有显式*alloc调用的函数,并且没有调用任何可能分配的库函数,比如strdup.
我必须查看生成的程序集才能意识到它是由于包含VLA的内联函数.

我认为VLA必须是堆栈分配的.这个编译器坏了吗?

c heap-memory variable-length-array

6
推荐指数
2
解决办法
1064
查看次数

C:如何使数组的大小动态化?

我从书中读到:«C Primer Plus»告诉我C99标准,可以使用如下的语法:

    int b=4;
    char a[b];
Run Code Online (Sandbox Code Playgroud)

但是当我把这段代码放到vs2013中时,它告诉我"表达式必须有一个常量值".

这本书错了吗?或者有一些我不知道的关于vs2013的新功能?

c arrays c99 c11 visual-studio-2013

2
推荐指数
1
解决办法
2032
查看次数

C 中表达式必须具有常量值

int LCS_length(char* x, char* y)
{
    int m = strlen(x);
    int n = strlen(y);

    char b[m + 1][n + 1];
    char c[m + 1][n + 1];
}
Run Code Online (Sandbox Code Playgroud)

在这段代码中,我想声明一个新的二维数组,但我的编译器给我写了这个错误:

表达式必须具有常量值

谁知道我能做什么,因为编译器不允许我用 C 语言执行此语句?

注意:它只是代码的一部分,后面有 return 语句。

c arrays

2
推荐指数
1
解决办法
1757
查看次数

C 中可变长度数组的动态内存分配

什么时候用 calloc 实例化可变长度数组比用 C 中的“普通”数组声明更好?

考虑“数组声明”方法:

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

int main(int argc, char *argv[])
{

    int n = atoi(argv[1]);
    int x[n];

    for(int i = 1; i < n; i++){
        x[i] = i;
        printf("%i", x[i]);
        printf("\n");
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

与 calloc 方法相比:

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

int main(int argc, char *argv[])
{

    int n = atoi(argv[1]);
    int * x = (int*) calloc(n, sizeof(int));

    for(int i = 1; i < n; i++){
        x[i] = i;
        printf("%i", x[i]);
        printf("\n");
    }
    return …
Run Code Online (Sandbox Code Playgroud)

c variable-length-array

0
推荐指数
1
解决办法
1149
查看次数

询问 (char*) 的 malloc

我只是想知道为什么

students[x].firstName=(char*)malloc(sizeof(char*));
Run Code Online (Sandbox Code Playgroud)

这个不需要字符串的长度。

完整代码(来自互联网上的某个地方):

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

int main(int argc, char** argv)
{
    typedef struct
    {
        char* firstName;
        char* lastName;
        int rollNumber;

    } STUDENT;

    int numStudents=2;
    int x;
    STUDENT* students = (STUDENT *)malloc(numStudents * sizeof *students);
   
    for (x = 0; x < numStudents; x++)
    {
        students[x].firstName=(char*)malloc(sizeof(char*));
       
        printf("Enter first name :");
        scanf("%s",students[x].firstName);
        students[x].lastName=(char*)malloc(sizeof(char*));
        printf("Enter last name :");
        scanf("%s",students[x].lastName);
        printf("Enter roll number  :");
        scanf("%d",&students[x].rollNumber);
    }

    for (x = 0; x < numStudents; x++)
        printf("First Name: %s, Last Name: %s, Roll number: …
Run Code Online (Sandbox Code Playgroud)

c dynamic-memory-allocation

0
推荐指数
1
解决办法
187
查看次数

为什么我们不能拥有大的 VLA 并(部分)取代 malloc

通常,当我们事先不知道所需的大小时,我们使用 malloc() ,如下所示(删除检查/错误处理等):

FILE * fp = fopen(path, "rb");
fseek(fp, 0, SEEK_END);
ssize_t length = ftell(fp);
rewind(fp);
char* buffer = malloc(length * sizeof(char));
fread(buffer, 1, *length, fp);
fclose(fp);
free(buffer);
Run Code Online (Sandbox Code Playgroud)

我们需要使用char* buffer = malloc(length * sizeof(char));而不是char buffer[length];因为堆栈的大小非常有限。我的问题是,由于 C 支持可变长度数组,至少对于局部变量来说,是什么阻止我们使堆栈变得更大而只使用堆栈内存呢?

我确实在这里找到了答案。它提出了一个有效的观点:malloc有一个接口可以报告内存的不可用性。但这是唯一char* buffer = malloc(length * sizeof(char));;有效和char buffer[length];无效的原因吗?

让我总结一下评论/答案提出的一些观点:

  1. malloc()返回NULL表示分配失败,而VLA没有这种设计,所以只有系统内存耗尽时程序才会崩溃;
  2. 由于其本地作用域,我们无法将本地 VLA 从被调用者函数返回给调用者;
  3. 我们不能realloc()动态调整VLA的大小;
  4. VLA 不是 ISO C 标准中的必需功能,因此某些平台可能不支持它。

(但如上面的例子所示,在很多情况下,我们只是想要一个巨大的本地VLA,其大小在运行时已知,但一旦知道就永远不会改变。但我们仍然必须使用malloc()它)

编辑: 许多人发现问题的意图不清楚,“为什么这么麻烦而不只是使用 …

c

-1
推荐指数
1
解决办法
180
查看次数