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

3

通常我总是这样编译我的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 - undefined
1
如果这是一个C++程序,请不要使用mallocfree。请尝试使用newdelete代替。 - undefined
4
那么为什么要打C++标签呢?为什么要使用g++?如果只能用C,就写C代码,并将其编译为C代码。 - undefined
1
@Voo 这是我老师的要求,我们只能使用g++和C语言。 - undefined
3
@Gerard:这比令人恼火更糟糕;在某些基本领域,C和C ++的语义不同(字符常量的大小和类型,C风格字符串的类型,void指针的处理等)。 如果他要求您使用C++编译器编译C代码,那么他会给您日后带来问题。没有好的理由支持这样做。 - undefined
显示剩余6条评论
3个回答

5
问题是你正在使用的特性(可变长度数组或VLA)是C99特性,不属于C++标准,但gcc支持它作为扩展-pedantic将强制gcc在使用扩展时发出警告,-Werror将使警告成为错误,从而有效地防止您使用扩展。
如果您能够使用C++,则可以使用std::vector。另一种选择是使用动态分配,通过newmalloc取决于您允许使用哪个。

似乎你必须使用C++编译器来编写C程序,这有点奇怪。我至少希望你可以使用-x c命令让g++作为C编译器。这里有一篇文章介绍了C和C++的兼容性,你也应该阅读Keith的评论。


@ShafikYaghmour 我的老师强制要求我们使用 g++ 编译器和 C 语言 :( - undefined
5
@Gerard:你的老师犯了一个严重的错误。g++ 不是 C 编译器,而是 C++ 编译器,C 绝对不是 C++ 的一个合适子集。主要问题是 C++ 强制对 malloc 的结果进行强制类型转换,这在 C 中是合法但是风格较差的写法(int *p = malloc(sizeof *p); 是有效的 C 代码,但是 C++ 不进行隐式转换)。如果你只能使用 g++,请确保你的代码可以通过 g++ -Wall -Wextra -Werror -pedantic -std=c++0xgcc -Wall -Wextra -Werror -pedantic -std=c99 这两种编译器进行无误编译。 - undefined
@crashmstr 如果我能的话,我会的 :) - undefined
@KeithThompson 如果文章的链接有效,我也会将这个之前的帖子添加到我的答案中,但不幸的是,顶部答案链接到的文章似乎无法打开。 - undefined

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);

7
@Gerard,你在上什么脑残学校?使用C语言编写却用C++编译器是错误的。就像用C编译器编译C++代码一样,你根本做不到这点。 - user529758

1

200: vector *v[n]; 可以通过初始化向量来解决:

vector* v = new vector[n];

207: float nfloat[numsvector]; 可以通过动态分配数组来解决:

float* nfloat = new float[numsvector]

我相信这些是相应的 C 内存分配方式:
vector* v = malloc(n * sizeof(vector));

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

2
注意,他的代码声明了一个同名的结构体,vector。 - undefined
问题是关于在C中构建一个vector,而不是使用std::vector - undefined
@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: 在函数‘int main()’中: eda.c:225: 错误:ISO C++禁止变长数组‘v’ eda.c:225: 错误:变长对象‘v’可能无法初始化 - undefined
@H2CO3 请解释一下。 - user2880462
1
在C语言中,你不应该对malloc的返回值进行强制类型转换,这是被不赞同的做法。这是将C代码与C++一起编译变得完全愚蠢的差异之一。 - undefined
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接