ISO C++ 禁止可变大小数组(编译错误)

Posted

技术标签:

【中文标题】ISO C++ 禁止可变大小数组(编译错误)【英文标题】:ISO C++ forbids variable-size array (compilation error) 【发布时间】:2013-10-16 19:28:50 【问题描述】:

通常我总是这样编译我的 C 代码:g++ program.c -o program.exe

但是我的大学教授要求我编译使用:g++ -o -Wall -Wextra -Werror -pedantic -std=c++0x program.exe program.c

(这对我来说是新的)。

所以...我运行命令并收到以下错误:

eda.c: In function ‘int main()’:
eda.c:200: error: ISO C++ forbids variable-size array ‘v’
eda.c:207: error: ISO C++ forbids variable-size array ‘nfloat’
cc1plus: warnings being treated as errors
eda.c:215: warning: suggest a space before ‘;’ or explicit braces around empty body in         ‘while’ statement

这是我程序的代码:

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


typedef struct 
    float* data;
    int size;
 vector;


/* Metodos Básicos */
vector *create_vector(int n, float* comps)
    vector *newvect = (vector*)malloc(sizeof(*newvect));
    newvect->data = (float*)malloc(n*sizeof(float));
    memcpy(newvect->data, comps, sizeof(float) * n);
    newvect->size = n;
    return newvect;


void destroy_vector(vector* v)
    free(v->data);
    free(v);


void print(vector* v)
    int size = v->size, i;
    for (i = 0; i < size; ++i)
    
        if(i == 0) printf("[%.1f,", v->data[i]);
        else if(i == (size-1)) printf("%.1f]\n", v->data[i]);
        else printf("%.1f,", v->data[i]);
    


/* Metodos Intermedios */
float dotDiferentSizes(vector* v1, vector* v2, int smax, int smin)
    double product;
    int i;
    for(i = 0; i < smin; i++)
        product += (v1->data[i])*(v2->data[i]); // += means add to product
    
    for(i = smin; i < smax; i++)
        product += (v1->data[i])*0; // += means add to product
    
    return product;


float dot(vector* v1, vector* v2)
    int smax = (v1->size), smin;
    int v1size = smax;
    int v2size = (v2->size);
    float product = 0.0;
    if (v2->size > smax) 
        smax = v2->size; //max_size checking
        smin = v1->size; //min_size checking
    
    else if (v2->size < smax)
            smin = v2->size;
    
    else smin = smax;
    // compute
    if(smax == smin)
        int i;
        for(i = 0; i < smin; i++)
            product += (v1->data[i])*(v2->data[i]); // += means add to product
        
    
    else
        if(v1size == smax)
            product = dotDiferentSizes(v1,v2,smax,smin); //v1>v2
        
        if(v2size == smax)
            product = dotDiferentSizes(v2,v1,smax,smin); 
        
    
    return product;


float norm(vector* v)
    int size = v->size, i;
    float norm = 0.0;
    for(i= 0; i < size; i++)
        norm += (v->data[i])*(v->data[i]);
    
    norm = sqrt( norm );
    return norm;


void normalize(vector* v)
    int size = v->size, i;
    float norma = 0.0;
    norma = norm(v);
    for(i= 0; i< size; i++)
        v->data[i] = v->data[i] / norma;
    
    for (i = 0; i < size; ++i)
    
        if(i == 0) printf("NORMALIZED VECTOR:[%.2f,", v->data[i]);
        else if(i == (size-1)) printf("%.2f]\n", v->data[i]);
        else printf("%.2f,", v->data[i]);
    


/* Metodos Avanzados */
vector* add(vector* v1, vector* v2)
    vector *vadd;
    int v1size, v2size, i;
    v1size = v1->size;
    int size = v1size;
    v2size = v2->size;
    if(v2size > v1size) 
        size = v2size;
        vadd = create_vector(size, v2->data);
        for(i = 0; i < v1size; i++)
            vadd->data[i] += v1->data[i];
        
    
    else 
        vadd = create_vector(size, v1->data);
        for(i = 0; i < v1size; i++)
            vadd->data[i] += v2->data[i];
        
    
    return(vadd);


vector* sub(vector* v1, vector* v2)
    vector *vsub;
    int v1size, v2size, i;
    v1size = v1->size;
    int size = v1size;
    v2size = v2->size;
    if(v2size > v1size) 
        size = v2size;
        vsub = create_vector(size, v2->data);
        for(i = 0; i < v1size; i++)
            vsub->data[i] = v1->data[i] - vsub->data[i]; /* restamos siempre v1 - v2*/
         /* en el bucle forzamos a restar v1 - v2, evitando el caso v2 - v1*/
        for(i = v1size; i < size; i++)
            vsub->data[i] = (v2->data[i])*(-1);
        
    
    else  /* v1size >= v2size */
        vsub = create_vector(size, v1->data);
        for(i = 0; i < v2size; i++)
            vsub->data[i] -= v2->data[i];
        
    
    return(vsub);


void incr(vector* source, vector* other)
    int smax, i, ssize = source->size, osize = other->size;
    vector *vincr;
    if(ssize > osize) smax = ssize;
    else 
        if(ssize < osize) smax = osize;
        else smax = ssize;
    
    vincr = add(source, other);
    if(ssize > osize)
        for(i = 0; i < smax; i++)
            source->data[i] = vincr->data[i];
        
    
    else
        source->data = (float*)realloc(source->data, sizeof(float) * smax);
        source->size = smax;    
        for(i = 0; i < smax; i++)
            source->data[i] = vincr->data[i];
        
    
    print(source);
    free(vincr);


//NumsVector, funcion que nos devuelve el numero de "numeros" que hay en cada vector del .txt,
//es decir, los n floats por cada vector

int NumsVector(char *linea, ssize_t size)
    int numsvector = 1; //Inicializamos a 1 ya que no podemos suponer valor maximo segun enunciado, pero si minimo >= 1
    int n;
    for(n = 2; n<= size; n++) //como ya suponemos que el primer valor despues del corchete es un numero y ya lo hemos contado, empezamos en 2
        if (linea[n] != '[' && linea[n] != ']')
            if(linea[n] == 44)
                numsvector = numsvector + 1;
            
        
    
    return numsvector;



int main()
    int n, i;
    scanf("%d\n", &n);
    vector *v[n];
    for(i = 0; i<n; ++i)  
        char *line = NULL;  //ponemos *line y len a valores 0 y null para que automaticamente getline nos haga el malloc y nos asigne el tamanyo
        size_t len = 0;
        ssize_t read; //en la variable read guardamos el valor de getline, contiene el numero de caracteres que tiene el string
        read = getline(&line,&len,stdin);
        int numsvector = NumsVector(line, read); 
        float nfloat[numsvector]; //sabemos el tamanyo del vector que hemos leido, creamos array de floats y lo llenamos de los floats
        //empieza el proceso para obtener los floats a partir de string de chars
        int j = 0;
        line[strlen(line) - 1] = ','; /* Replaces the end ] with a , */
        char *p = line + 1; /* creates a new pointer, pointing after the first [ in the original string */
        do
        
            sscanf(p, "%f,", &nfloat[j]); /* grabs up to the next comma as a float */       
            while (*(p++) != ',') ; /* moves pointer forward to next comma */
        
        while (++j < numsvector); /* stops when you've got the expected number */     
        v[i] = create_vector(numsvector, nfloat);//conseguimos almacenar el contenido del string en un vector del tipo float (nfloat)
        int aux;
        for(aux = 0; aux<numsvector; ++aux) 
            printf("V[%d]->data[%d] = : %.1f\n", i, aux, v[i]->data[aux]); //test de que la memoria se almacena bien, luego se borra
        
        free(line);
    

这些是给出错误的行:

200: vector *v[n];
207: float nfloat[numsvector];
215: while (*(p++) != ',') ; //Now I think works fine with the extra space..

有人可以帮我编译文件吗?

【问题讨论】:

你确定要C++ 吗?这段代码在我看来像 C 如果这是一个 C++ 程序,不要使用mallocfree。请改用newdelete @Gerard 那么为什么这个标签是 C++ 呢?你为什么使用g++?如果只能用C,那就写C代码,编译成C代码。 @Voo 是我老师的愿望,我们只能用g++和c语言 @Gerard:这比烦人还糟糕; C 和 C++ 在一些基本领域(字符常量的大小和类型、c 样式字符串的类型、void 指针的处理等)具有不同的语义。如果他要求你用 C++ 编译器 编译 C 代码,那么他就是在为你以后的问题做准备。没有充分的理由。 【参考方案1】:

问题在于您正在使用的功能(可变长度数组或VLA)是C99功能,不是C++的一部分em> 标准,但gcc 支持它作为extension,-pedantic 将强制gcc 在您使用扩展程序时警告您,-Werror 将发出警告错误,这将有效地阻止您使用扩展程序。

如果您能够使用C++,一个选择是使用std::vector。另一种选择是通过newmalloc 使用动态分配,具体取决于您可以使用哪个。

这有点奇怪,您似乎必须在 C 中编程但使用 C++ 编译器,我希望至少您可以使用 -x c 来使g++ 充当C 编译器。这是一篇涵盖 Compatibility of C and C++ 的文章,您还应该阅读 Keith 的 cmets。

【讨论】:

@ShafikYaghmour 我的老师强迫我们使用g++编译器和C语言:( @Gerard:你的老师犯了一个严重的错误。 g++ 不是 C 编译器,它是 C++ 编译器,而且 C 绝对不是 C++ 的真子集。主要问题是 C++ 强制对 malloc 的结果进行强制转换,这在 C 中是合法的但风格很差(int *p = malloc(sizeof *p); 是有效的 C,但 C++ 不进行隐式转换)。如果这是您遇到的问题,请确保您的代码使用 both g++ -Wall -Wextra -Werror -pedantic -std=c++0x gcc -Wall -Wextra Werror -pedantic -std=c99` 编译干净。 @crashmstr 如果可以的话我会:) @KeithThompson 我也会将此previous thread 添加到我的答案中,但可惜文章的最佳答案链接似乎不起作用。【参考方案2】:

通常我总是这样编译我的 C 代码:g++ program.c -o program.exe

这是不正确的。 g++ 是 C++ 编译器,而不是 C 编译器。 (我知道,您可以指定 -x c 来强制使用该语言,但是当您也有 C 编译器时,为什么还要这样做呢?)

C 代码应使用 C 编译器进行编译。 C++ 代码应使用 C++ 编译器进行编译。任何其他组合都是错误的。

如果您需要编写 C++ 代码,请编写 C++ 代码。在 C++ 中,您不能拥有 C99 样式的可变长度数组。您将需要改用std::vector。像这样:

std::vector<some_type> theVector(initial_size);

【讨论】:

@Gerard 你上什么样的脑死亡学校?将 C 与 C++ 编译器一起使用是错误的。就像使用 C 编译器编译 C++ 代码一样。你只是不能那样做。【参考方案3】:

200: 向量 *v[n];可以通过初始化向量来修复:

vector* v = new vector[n];

207: 浮动 nfloat[numsvector];可以通过动态分配数组来修复:

float* nfloat = new float[numsvector]

我相信这些是相应的 C 内存分配:

vector* v = malloc(n * sizeof(vector));

float* nfloat = malloc(numsvector * sizeof(float));

【讨论】:

注意,他的代码声明了一个同名的结构体,vector。 问题是关于在C 中构建一个vector,而不是使用std::vector 我已经编辑了代码,所以它不使用 std::vector。现在只有内存分配需要在 C 中。 @DaanKolthof nfloat 的内存分配有效,非常感谢!但是对于 v 我认为是不正确的,我尝试了:vector *v[n] = (vector*)malloc(sizeof(*v[n])); 然后我进入屏幕:iMac-de-Gerard:Desktop Gera$ g++ -Wall -Wextra -Werror -pedantic -o eda.exe eda.c eda.c: In function ‘int main()’: eda.c:225: error: ISO C++ forbids variable-size array ‘v’ eda.c:225: error: variable-sized object ‘v’ may not be initialized跨度> 在 C 语言中你不会返回 malloc,这是不受欢迎的。这是使使用 C++ 编译 C 代码成为一个完全愚蠢的想法的差异之一。

以上是关于ISO C++ 禁止可变大小数组(编译错误)的主要内容,如果未能解决你的问题,请参考以下文章

错误:ISO C++ 禁止声明没有类型的“对象”

编译器错误? g++ 允许可变大小的静态数组,除非函数是模板化的

错误:ISO C++ 禁止在新数组中初始化

: 警告: ISO C++ 禁止变长数组‘s1’ [-Wvla]

java 数组类比较编译报错问题

使用 MSVC C++ 编译器创建动态大小的数组